Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Golang 中的方法和接收者 #46

Open
lqshow opened this issue Sep 22, 2018 · 0 comments
Open

Golang 中的方法和接收者 #46

lqshow opened this issue Sep 22, 2018 · 0 comments
Labels

Comments

@lqshow
Copy link
Owner

lqshow commented Sep 22, 2018

方法和接收者

方法的声明

方法声明和函数声明只有一点差别,只是在关键字func方法名之间多加了一个参数。这个参数把这个方法绑定到这个参数对应的类型上。

类型拥有的所有方法名都必须是唯一的,因为每一个类型都有它自己的命名空间,所以不同类型可以使用相同的方法名。

方法的接收者

以下方法声明里的参数 t 就是这个方法的接收者

func (t *Type) Method() {} // pointer receiver
func (t Type) Method() {} // value receiver

pointer receiver

指针接收者,接收者的类型是一个指针,是接收者的引用,对这个引用的修改之间影响真正的接收者

value receiver

值接收者,接收者的类型是一个值,传递给方法的实际上是值的一个副本,方法内部无法对其真正的接收者做更改

使用时存在两种隐式转换

指针方法和值方法都可以在指针或非指针上被调用

  1. 值类型的接收者也可以使用指针类型的调用(实参接收者是 *T 类型的变量,而形参接收者是 T 类型,编译器会隐式的解引用接收者,获取实际的取值 )

    a.printName()   	// 隐式转换为(*a)
  2. 指针类型的接收者也可以使用值类型的调用(实参接收者是 T 类型的变量,而形参接收者是 *T 类型,编译器会隐式的获取变量的地址)

    f.setName("Fred1")   // 隐式转换为(&f)

示例代码

// 这个 `person` 结构体有两个字段
type Person struct {
	name string
	age  int
}

// 定义普通函数
func printName(name string) {
	fmt.Printf("Name is %s \n", name)
}

// 定义 Person 类型的方法(函数名前面多加了一个参数, 这个 p 是这个方法的接收者)
// 定义值接收者
func (p Person) printName() {
	fmt.Printf("Name is %s \n", p.name)
}

// 定义指针接收者
func (p *Person) setName(name string) {
	p.name = name
}
a := &Person{name: "Ann", age: 40}
a.setName("Ann1")
// 值类型的接收者也可以使用指针类型的调用
a.printName()   // 隐式转换为(*a)
// 实际上编译器,已经对该类型进行了如下转换
(*a).printName()
f := Person{name: "Fred", age: 30}
// 虽然 setName 这个方法要求接收者是一个指针,但我们可以使用简写
// 实际上编译器会对变量进行 &f 的隐式转换(只允许变量)
f.setName("Fred1")   // 隐式转换为(&f)
(&f).setName("Fred2")

f.printName() 

在定义方法接收者时,应该使用指针接收者还是值接收者?

什么时候该使用 pointer receiver

  1. 如果想在方法中改变接收者的状态,操作它的值,使用指针接收器。
  2. 效率:如果实参定义的 struct 很大,避免复制整个实参。
  3. 一致性:习惯上遵循如果 Struct 的任何一个方法使用了指针接收者,那么所有的 struct 方法都应该使用指针接收者,即使有些方法并不一定需要。

什么时候使用 value receiver

  1. 如果不需要编辑接收者的值

参考

@lqshow lqshow added the Golang label Sep 22, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant