如果一個函數有接收者,那麼這個函數就叫方法。
Go 語言裡有兩種類型的接收者:值接收者和指針接收者。如下:
// user 在程式裡定義一個使用者類型
type user struct {
name string
email string
}
// notify 使用值接收者實作了一個方法
func (u user) notify() {
fmt.Printf("Sending User Email To %s<%s>\n",
u.name,
u.email)
}
// changeEmail 使用指針接收者實作了一個方法
func (u *user) changeEmail(email string) {
u.email = email
}
有兩個概念:調用者和接收者,這兩者都可以是值和指針。
1 使用值接收者聲明方法,調用時會使用這個值的一個副本來執行:
1.1 使用值來調用:
bill := user{"Bill", "[email protected]"}
bill.notify()
notify方法會接收到一個bill的副本,然後進行操作。
1.2 使用指針來調用:
lisa := &user{"Lisa", "[email protected]"}
lisa.notify()
notify 操作的是一個副本,隻不過這次操作的是從 lisa 指針指向的值的副本。Go 編譯器為了支援這種方法調用背後做的事情就 是将指針解引用為值。實際上執行的類似于:
(*lisa).notify()
2 使用指針接收者,方法會共享調用方法時接收者所指向的值:
2.1 使用指針來調用:
lisa := &user{"Lisa", "[email protected]"}
// 指向 user 類型值的指針可以用來調用
// 使用指針接收者聲明的方法
lisa.changeEmail("[email protected]")
一旦 changeEmail 調用傳回,這個調用對值做的修改也會反映在 lisa指針所指向的值上。這是因為 changeEmail 方法使用了指 針接收者。
2.3 使用值來調用:
bill := user{"Bill", "[email protected]"}
// user 類型的值可以用來調用
// 使用指針接收者聲明的方法
bill.changeEmail("[email protected]")
Go 語言再一次對值做了調整,使之符合函數的接收者,進行調用,也就是先引用 bill 值得到一個指針,這樣這個指針就能夠 匹 配方法的接收者類型,再進行調用。實際上執行的類似于:
(&bill).changeEmail ("[email protected]")
總結一下,值接收者使用值的副本來調用方法,而指針接受者使用實際值來調用方法。具體需要用什麼來作為使用者就看你的功能裡面需要什麼來做選擇了。