標籤:not net when 使用 original can too 指標 選擇
何時使用實值型別
1.如果接受者是一個 map,func 或者 chan,使用實值型別(因為它們本身就是參考型別)。
2.如果接受者是一個 slice,並且方法不執行 reslice 操作,也不重新分配記憶體,使用實值型別。
3.如果接受者是一個小的數組或者原生的實值型別結構體類型(比如 time.Time 類型),而且沒有可修改的欄位和指標,又或者接受者是一個簡單地基本類型像是 int 和 string,使用實值型別就好了。
一個實值型別的接受者可以減少一定數量的垃圾產生,如果一個值被傳入一個實值型別接受者的方法,一個棧上的拷貝會替代在堆上分配記憶體(但不是保證一定成功),所以在沒搞明白代碼想幹什麼之前,別因為這個原因而選擇實值型別接受者。
何時使用指標類型
1.如果方法需要修改接受者,接受者必須是指標類型。
2.如果接受者是一個包含了 sync.Mutex 或者類似同步欄位的結構體,接受者必須是指標,這樣可以避免拷貝。
3.如果接受者是一個大的結構體或者數組,那麼指標類型接受者更有效率。(多大算大呢?假設把接受者的所有元素作為參數傳給方法,如果你覺得參數有點多,那麼它就是大)。
4.從此方法中並發的調用函數和方法時,接受者可以被修改嗎?一個實值型別的接受者當方法調用時會建立一份拷貝,所以外部的修改不能作用到這個接受者上。如果修改必須被原始的接受者可見,那麼接受者必須是指標類型。
5.如果接受者是一個結構體,數組或者 slice,它們中任意一個元素是指標類型而且可能被修改,建議使用指標類型接受者,這樣會增加程式的可讀性
當你看完這個還是有疑慮,還是不知道該使用哪種接受者,那麼記住使用指標接受者。
- If the receiver is a map, func or chan, don‘t use a pointer to them. If the receiver is a slice and the method doesn‘t reslice or reallocate the slice, don‘t use a pointer to it.
- If the method needs to mutate the receiver, the receiver must be a pointer.
- If the receiver is a struct that contains a sync.Mutex or similar synchronizing field, the receiver must be a pointer to avoid copying.
- If the receiver is a large struct or array, a pointer receiver is more efficient. How large is large? Assume it‘s equivalent to passing all its elements as arguments to the method. If that feels too large, it‘s also too large for the receiver.
- Can function or methods, either concurrently or when called from this method, be mutating the receiver? A value type creates a copy of the receiver when the method is invoked, so outside updates will not be applied to this receiver. If changes must be visible in the original receiver, the receiver must be a pointer.
- If the receiver is a struct, array or slice and any of its elements is a pointer to something that might be mutating, prefer a pointer receiver, as it will make the intention more clear to the reader.
- If the receiver is a small array or struct that is naturally a value type (for instance, something like the time.Time type), with no mutable fields and no pointers, or is just a simple basic type such as int or string, a value receiver makes sense. A value receiver can reduce the amount of garbage that can be generated; if a value is passed to a value method, an on-stack copy can be used instead of allocating on the heap. (The compiler tries to be smart about avoiding this allocation, but it can‘t always succeed.) Don‘t choose a value receiver type for this reason without profiling first.
- Finally, when in doubt, use a pointer receiver.
注意:如果方法接受者是基礎類型,使用值即可,由於基礎類型無法直接取地址,無法自轉換為指標模式,使用值接受者即可,其他的都可以使用指標接受者如下會報錯:
type INT int
i := &INT(3)
參考:
Go Code Review Comments
Go 語言方法接受者類型的選擇
go語言接受者的選取