在 Go 語言裏,方法和函數只差了一個,那就是方法在 func
和標識符之間多了一個參數。編程
type user struct { name string, email string, } //這是函數的定義 func notify(email string) { fmt.Println("Email is %s", email) } //這是方法的定義 func (u user) notify(email string) { fmt.Println("Email is %d", email) }
咱們能夠看到,方法是在 func
和 notify
之間多了一個 user
類型的參數 u
,這個 u
就稱做接收者。編程語言
爲何有了函數,還須要方法?函數
Go 不是純粹的面向對象編程語言,並且Go不支持類。所以,基於類型的方法是一種實現和類類似行爲的途徑。spa
相同的名字的方法能夠定義在不一樣的類型上,而相同名字的函數是不被容許的指針
接收者有兩種,一種是值接收者,一種是指針接收者。顧名思義,值接收者,是接收者的類型是一個值,是一個副本,方法內部沒法對其真正的接收者作更改;指針接收者,接收者的類型是一個指針,是接收者的引用,對這個引用的修改之間影響真正的接收者。像上面程序同樣定義方法,將 user
改爲 *user
就是指針接收者。code
package main import ( "fmt" ) type user struct { name string email string } func (u user)changeName(name string) { u.name = name } func (u *user) changeEmail(email string) { u.email = email } func main() { u1 := user{ "linlin", "11223@qq.com", } fmt.Println("name:",u1.name) u1.changeName("liming") fmt.Println("name:",u1.name) fmt.Println("email:",u1.email) u1.changeEmail("1221333333@qq.com") fmt.Println("email:",u1.email) }
結果爲:對象
name: linlin name: linlin email: 11223@qq.com email: 1221333333@qq.com
注意:Go語言讓咱們能夠直接使用u1.changeName("liming")
。u1.changeName("liming")
會自動被Go語言解釋爲 (&u1).changeName("liming")
。blog
何時使用指針接收器,何時使用值接收器?string
通常來講,指針接收器可使用在:對方法內部的接收器所作的改變應該對調用者可見時。面向對象編程
指針接收器也能夠被使用在以下場景:當拷貝一個結構體的代價過於昂貴時。考慮下一個結構體有不少的字段。在方法內使用這個結構體作爲值接收器須要拷貝整個結構體,這是很昂貴的。在這種狀況下使用指針接收器,結構體不會被拷貝,只會傳遞一個指針到方法內部使用。
在其餘的全部狀況,值接收器均可以被使用。