Open lqshow opened 5 years ago
方法声明和函数声明只有一点差别,只是在关键字func和方法名之间多加了一个参数。这个参数把这个方法绑定到这个参数对应的类型上。
func
方法名
类型拥有的所有方法名都必须是唯一的,因为每一个类型都有它自己的命名空间,所以不同类型可以使用相同的方法名。
以下方法声明里的参数 t 就是这个方法的接收者
func (t *Type) Method() {} // pointer receiver
func (t Type) Method() {} // value receiver
指针接收者,接收者的类型是一个指针,是接收者的引用,对这个引用的修改之间影响真正的接收者
值接收者,接收者的类型是一个值,传递给方法的实际上是值的一个副本,方法内部无法对其真正的接收者做更改
指针方法和值方法都可以在指针或非指针上被调用
值类型的接收者也可以使用指针类型的调用(实参接收者是 *T 类型的变量,而形参接收者是 T 类型,编译器会隐式的解引用接收者,获取实际的取值 )
a.printName() // 隐式转换为(*a)
指针类型的接收者也可以使用值类型的调用(实参接收者是 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()
方法和接收者
方法的声明
方法声明和函数声明只有一点差别,只是在关键字
func
和方法名
之间多加了一个参数。这个参数把这个方法绑定到这个参数对应的类型上。类型拥有的所有方法名都必须是唯一的,因为每一个类型都有它自己的命名空间,所以不同类型可以使用相同的方法名。
方法的接收者
pointer receiver
指针接收者,接收者的类型是一个指针,是接收者的引用,对这个引用的修改之间影响真正的接收者
value receiver
值接收者,接收者的类型是一个值,传递给方法的实际上是值的一个副本,方法内部无法对其真正的接收者做更改
使用时存在两种隐式转换
值类型的接收者也可以使用指针类型的调用(实参接收者是 *T 类型的变量,而形参接收者是 T 类型,编译器会隐式的解引用接收者,获取实际的取值 )
指针类型的接收者也可以使用值类型的调用(实参接收者是 T 类型的变量,而形参接收者是 *T 类型,编译器会隐式的获取变量的地址)
示例代码
在定义方法接收者时,应该使用指针接收者还是值接收者?
什么时候该使用 pointer receiver
什么时候使用 value receiver
参考