
方法能给用户定义的类型添加新的行为,实际上方法也是函数,只是在声明时在关键字 fun 和方法名之间增加了一个参数。
package main
import "fmt"
// 用户定义的类型 / 结构体
type User struct {
name string
score int64
}
// 使用值接收者实现了一个方法
func (u User) QueryScore() {
fmt.Printf("Query %s --> score:%d\n", u.name, u.score)
}
// 使用指针接收者实现了一个方法
func (u *User) changeScore(score int64) {
u.score = score
}
func main() {
// User 类型的值可以用来调用
oscar := User{"Oscar", 100}
// 使用值接收者声明的方法
oscar.QueryScore()
// 指向 User 类型的指针也可以用来调用
lisa := &User{"Lisa", 88}
// 使用指针接收者声明的方法
lisa.QueryScore()
// 使用指针接收者声明的方法
oscar.changeScore(68)
oscar.QueryScore()
// 使用指针接收者声明的方法
lisa.changeScore(77)
lisa.QueryScore()
}
关键字 func 和函数名之间的参数被称做接收者,将函数与接收者的类型绑在一起。 如果一个函数有接收者,这个函数就被成为方法。 Go 语言中有两种类型的接收者:值接收者和指针接收者。
1、使用值接收者声明一个方法
func (u User) QueryScore() {}
QueryScore 方法的接收者被声明为 User 类型的值。如果使用值接收者声明方法,调用时会使用这个值的一个副本来执行。
// User 类型的值可以用来调用
oscar := User{"Oscar", 100}
// 使用值接收者声明的方法
oscar.QueryScore()
oscar.QueryScore() 这个语法与调用一个包里的函数看起来很类似,但在这个列子里 oscar 不是包名,而是变量名。这段程序在调用 QueryScore 方法时,使用 oscar 的值作为接收者进行调用,方法 QueryScore 会接收到 oscar 的值的一个副本。
也可以使用指针来调用使用值接收者声明的方法。
// 指向 User 类型的指针也可以用来调用
lisa := &User{"Lisa", 88}
// 使用指针接收者声明的方法
lisa.QueryScore()
声明一个名为 lisa 的指针变量,并使用指定的名字和分数地址做初始化。 使用 lisa 这个指针变量来调用 QueryScore 方法。
为了支持这种方法调用,Go 语言调整了指针的值, 来符合方法接收者的定义。可以认为 Go 语言执行了如下代码:
(*lisa).QueryScore()
指针被解引用为值,这样就符合了值接收者的要求。 QueryScore 操作的是一个副本,只不过这次操作的是从 lisa 指针指向的值的副本。
2、使用指针接收者声明方法
// 使用指针接收者实现了一个方法
func (u *User) changeScore(score int64) {
u.score = score
}
接收者类型是指向 User 类型值的指针,而不是 User 类型的值。 当调用使用指针接收者声明的方法时,这个方法会共享调用方法时接收者所指向的值。
// 指向 User 类型的指针也可以用来调用
lisa := &User{"Lisa", 88}
// 使用指针接收者声明的方法
lisa.changeScore(77)
声明了 lisa 指针变量。 使用 lisa 这个变量调用了 changeScore 方法。 一旦 changeScore 调用返回,这个调用对值做的修改也会反应在 lisa 指针所指向的值。
值接收者使用值的副本来调用方法,而指针接收者使用实际值来调用方法。
也可以使用一个值来调用指针接收者声明的方法。
oscar := User{"Oscar", 100}
oscar.changeScore(68)
声明一个变量 oscar 。 使用这个变量调用使用指针接收者声明的 changeScore 方法。
为了支持这种调用方法,Go 语言再一次对值做了调整,使之符合函数的接收者进行调用。
(&oscar).changeScore(99)
首先引用 oscar 值得到一个指针,这样这个指针就能够匹配方法的接收者类型,在进行调用。 Go 语言既允许使用值,也可以使用指针来调用方法,不必严格符合接收者的类型。
文章转载自零点小思随笔,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。