1. 程式人生 > >Go 語言的方法接受者用值型別還是指標型別??

Go 語言的方法接受者用值型別還是指標型別??

很多人在寫 Go 語言程式碼時經常會問一個問題,那就是一個方法的接受者型別到底應該是值型別還是指標型別呢,Go 的 wiki 上對這點做了很好的解釋。

何時使用值型別

  1. 如果接受者是一個 map,func 或者 chan,使用值型別(因為它們本身就是引用型別)。
  2. 如果接受者是一個 slice,並且方法不執行 reslice 操作,也不重新分配記憶體給 slice,使用值型別。
  3. 如果接受者是一個小的陣列或者原生的值型別結構體型別(比如 time.Time 型別),而且沒有可修改的欄位和指標,又或者接受者是一個簡單地基本型別像是 int 和 string,使用值型別就好了。

一個值型別的接受者可以減少一定數量的垃圾生成,如果一個值被傳入一個值型別接受者的方法,一個棧上的拷貝會替代在堆上分配記憶體(但不是保證一定成功),所以在沒搞明白程式碼想幹什麼之前,別因為這個原因而選擇值型別接受者。

何時使用指標型別

  1. 如果方法需要修改接受者,接受者必須是指標型別。
  2. 如果接受者是一個包含了 sync.Mutex 或者類似同步欄位的結構體,接受者必須是指標,這樣可以避免拷貝。
  3. 如果接受者是一個大的結構體或者陣列,那麼指標型別接受者更有效率。(多大算大呢?假設把接受者的所有元素作為引數傳給方法,如果你覺得引數有點多,那麼它就是大)。
  4. 從此方法中併發的呼叫函式和方法時,接受者可以被修改嗎?一個值型別的接受者當方法呼叫時會建立一份拷貝,所以外部的修改不能作用到這個接受者上。如果修改必須被原始的接受者可見,那麼接受者必須是指標型別。
  5. 如果接受者是一個結構體,陣列或者 slice,它們中任意一個元素是指標型別而且可能被修改,建議使用指標型別接受者,這樣會增加程式的可讀性

總結

當你看完這個還是有疑慮,還是不知道該使用哪種接受者,那麼記住使用指標接受者。

關於接受者的命名

社群約定的接受者命名是型別的一個或兩個字母的縮寫(像 c 或者 cl 對於 Client)。不要使用泛指的名字像是 me,this 或者 self,也不要使用過度描述的名字,最後,如果你在一個地方使用了 c,那麼就不要在別的地方使用 cl。