func (receiver receiver_type) some_func_name(arguments) return_values
从应用上讲,方法接受者分为值接收者,指针接收者,初级golang学者可能看过这两个接收者实际表现, 但是一直很混淆,很难记忆。
本次我们使用地址空间的角度来剖析实质,强化记忆。
值接受者: receiver是struct等值类型。
下面定义了值类型接受者Person, 尝试使用Person{}, &Person{}去调用接受者函数。
package mainimport "fmt"type Person struct { name string age int}func (p Person) say() { fmt.Printf("I (%p) ma %s, %d years old \n",&p, p.name,p.age)}func (p Person) older(){ // 值类型方法接受者: 接受者是原类型值的副本 p.age = p.age +1 fmt.Printf("I (%p) am %s, %d years old\n", &p, p.name,p.age)}func main() { p1 := Person{name: "zhangsan", age: 20} p1.older() p1.say() fmt.Printf("I (%p) am %s, %d years old\n",&p1, p1.name,p1.age) p2 := &Person{ name: "sili", age: 20} p2.older() // 即使定义的是值类型接受者, 指针类型依旧可以使用,但我们传递进去的还是值类型的副本 p2.say() fmt.Printf("I (%p) am %s, %d years old\n",p2, p2.name,p2.age)}尝试改变p1=Person{},p2=&Person{}的字段值:
I (0xc000098078) am zhangsan, 21 years oldI (0xc000098090) ma zhangsan, 20 years oldI (0xc000098060) am zhangsan, 20 years oldI (0xc0000980c0) am sili, 21 years oldI (0xc0000980d8) ma sili, 20 years oldI (0xc0000980a8) am sili, 20 years oldp1=Person{} 未能修改原p1的字段值; p2=&Person{}也未能修改原p2的字段值。
%p印证 (%p:输出地址值, 这两个非同一地址)。带来的效果是:对值类型接收者内的字段操作,并不影响原调用者。
方法接收者也可以定义在指针上,任何尝试对指针接收者的修改,会体现到调用者。
package mainimport "fmt"type Person struct{ name string age int}func (p Person) say(){ fmt.Printf("I (%p) am %s, %d years old\n", &p, p.name,p.age)}func (p *Person) older(){ // 指针接受者,传递函数内部的是原类型值(指针), 函数内的操作会体现到原指针指向的空间 p.age = p.age +1 fmt.Printf("I (%p) am %s, %d years old\n", p, p.name,p.age)}func main() { p1 := Person{"zhangsan",20} p1.older() // 虽然定义的是指针接受者,但是值类型依旧可以使用,但是会隐式传入指针值 p1.say() fmt.Printf("I (%p) am %s, %d years old\n", &p1, p1.name,p1.age) p2:= &Person{"sili",20} p2.older() p2.say() fmt.Printf("I (%p) am %s, %d years old\n", p2, p2.name,p2.age)}尝试改变p1= Person{}, p2=&Person{}字段值
I (0xc000098060) am zhangsan, 21 years oldI (0xc000098078) am zhangsan, 21 years oldI (0xc000098060) am zhangsan, 21 years oldI (0xc000098090) am sili, 21 years oldI (0xc0000980a8) am sili, 21 years oldI (0xc000098090) am sili, 21 years oldp1=Person{} 成功修改字段值,p2=&Person{}也成功修改字段值。
带来的效果: 任何对指针接收者的修改会体现到 原调用者。
接上例子:
Person.say(p1) (*Person).older(p2)依旧是 值类型/指针类型方法接收者的效果。
I (0xc0000040d8) am zhangsan, 21 years oldI (0xc0000040a8) am sili, 22 years old这种姿势相对于面向对象的接收者不常见。
func (p Person) printName() Person{ fmt.Printf("Name:%s", p.Name) return p}type myFloat float64func (m myFloat) ceil() float64 { return math.Ceil(float64(m))}以上是有态度的马甲记录的有关golang 方法接收者的全部用法,通过%p,我们探究了值类型/指针接收者的调用原理。
本文来自博客园,作者:{有态度的马甲},转载请注明原文链接:https://www.cnblogs.com/JulianHuang/p/16330427.html
欢迎关注我的原创技术、职场公众号, 加好友谈天说地,一起进化