iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 16
1
Software Development

Golang入門到進階實戰系列 第 16

Day16 Go語言的物件導向(2)

接收器

Go方法是作用在接收器(receiver)上的一個函數,接收器是某種類型的變量,因此方法是一種特殊類型的函數。

接收器類型可以是任何類型,不只是結構體類型,任何類型都可以有方法,甚至可以是函數類型,也可以是int、bool、string或陣列的別名類型。

但是接收器不能是一個接口類型,因為接口是一個抽象定義,而方法卻是具體實現,如果將接收器定義為接口類型,會引發一個編釋上的錯誤:invalid receiver type。

在面向對象編程裡,一個很重要的觀念是傳值或是傳引用,前者會複製一份參數讓方法使用,方法裡對參數的操作都不會影響傳入的參數數值,如果我們想要保存方法對參數的改動,那麼就必須選擇傳引用而非傳值。

值接收器

type user struct{
    name string
    age int
}
func (u user) func1(){
    //do something
}

值接收器操作的是值的拷敗,在函數內的操作皆不影響原來的數值。

指針接收器

func (u user) func12(){
    //do something
}

指針接收器傳遞的是引用,函數內所有的改動都會保存在參數裡頭。

使用時機

指針接收器

如果要在方法中更改接收器的狀態,操縱它的值,請使用指針接受器。如果方法綁定的結構體非常大,使用指針接收器會是比值接收器更加有效率。

值接收器

如果你不需要編輯接收器之值,請使用值接收器。值接收器是併發安全的,而指針接收器並不是併發安全的。

Go CodeReview的建義

對於新手來說,選擇在方法使用值或指針接收器可能有些困難,當新手有疑問時,就使用指針接收器。

  • 如果接收器是 map,func 或 chan,則不要使用指向它們的指針。如果接收器是切片並且該方法不重新切片或重新分配切片,則不要使用指向它的指針。
  • 如果該方法需要改變接收器,則接收器必須是指針。
  • 如果接收器是包含sync.Mutex或類似同步字段的結構,則接收器必須是避免覆制的指針。
  • 如果接收器是大型結構或數組,則指針接收器更有效。有多大?假設它相當於將所有元素作為參數傳遞給方法。如果感覺太大,對接收器來說也太大了。
  • 函數或方法可以同時或在從這種方法調用時改變接收器嗎?在調用方法時,值類型會創建接收器的副本,因此外部更新將不會應用於此接收器。如果必須在原始接收器中看到更改,則接收器必須是指針。
  • 如果接收器是結構,數組或切片,並且其任何元素是指向可能變異的東西的指針,則更喜歡指針接收器,因為它將使讀者更清楚地意圖。
  • 如果接收器是一個小數組或結構,它自然是一個值類型(例如,類似於 time.Time 類型),沒有可變字段和沒有指針,或者只是一個簡單的基本類型,如 int 或 string,值接收者是有道理的,值接收器可以減少生成的垃圾量;如果將值傳遞給值方法,則可以使用堆棧上的副本而不是在堆上進行分配。(編譯器試圖避免這種分配,但它不能總是成功。)不要為此而選擇值接收器類型而不先進行分析。

上一篇
Day15 Go語言的物件導向
下一篇
Day17 Interface接口
系列文
Golang入門到進階實戰30

1 則留言

0
ertclee
iT邦新手 5 級 ‧ 2020-11-16 14:34:24

指針接收器
func (u user) func12(){ --> u *user
//do something
}

Go CodeReview的建義 --> 建議

則接收器必須是避免覆制的指針。 --> 複製

我要留言

立即登入留言