暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Go 语言--方法

零点小思随笔 2021-06-24
509

方法能给用户定义的类型添加新的行为,实际上方法也是函数,只是在声明时在关键字 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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论