go指针接收者和值接收者的区别小结 go 接口 指针
目录
- go 指针接收者和值接收者的区别
- 易错点辨析
go 指针接收者和值接收者的区别
指针接收者和值接收者的区别主要有两点:
- Go 中函数传参是传值,因此指针接收者传递的是接收者的指针拷贝,值接收者传递的是接收者的拷贝&8212;在技巧中指针接收者的变量会被修改,而值接收者的成员变量修改是无效的(毕竟传入的是拷贝,修改的天然也是拷贝的成员变量)。
- 在接口实现上,如果值接收者实现了某个技巧,相当于值接收者和指针接收者都实现了这个技巧。反之则不行,即指针接收者实现了某个技巧,不能看成值接收者实现这个技巧。
注意第2点只影响接口实现,如果不涉及接口的话是不受到这条制度约束的。
一个助记的然而不太正确的见解:接收者是指针类型的技巧,很可能在技巧中会对接收者的属性进行更改操作,从而影响接收者;而对于接收者是值类型的技巧,在技巧中不会对接收者本身产生影响。
领会角度:指针接收者可以选择修改自己的值和不修改,值接收者修改自己的值是无效的(由于是拷贝)。因此可以看成指针接收者的能力>值接收者的能力,天然:指针接收者实现某个技巧可以看成值接收者实现某个技巧,反之则不行。
package mainimport “fmt”type coder interface code() debug()}type Gopher struct language string}func (p Gopher) code() fmt.Printf(“I am coding %s languagen”, p.language)}func (p *Gopher) debug() fmt.Printf(“I am debuging %s languagen”, p.language)}func main() var c coder = &Gopher”Go”} //运行正常 //上一行换成: var c coder = Gopher”Go”} // 则报错 Gopher does not implement coder (debug method has pointer receiver) c.code() c.debug()}
注意&x1f4e2;:对于&x1f446;&x1f3fb;上面的第 2 点补充:虽然隐式实现的技巧不一样,然而如果不涉及接口,单纯在调用的时候,无论是指针接收者还是值接收者实现了某个技巧,指针接收者和值接收者都可以调用。本质上是 go 的语法糖。
最佳操作:
如果类型具备“原始的本质”,即其成员都是由 Go 语言里内置的原始类型,如字符串,整型值等,那就定义值接收者类型的技巧。
内置的引用类型,如 slice,map,interface,channel,这些类型比较独特,声明他们的时候,实际上是创建了一个 header?, 对于他们也是直接定义值接收者类型的技巧。这样,调用函数时,是直接 copy 了这些类型的 header?,而 header? 本身就是为复制设计的。
如果类型具备非原始的本质,不能被安全地复制,这种类型总是应该被共享,那就定义指针接收者的技巧。
虽然上面是这么说,然而个人感觉在实际使用中,基本可以无脑使用指针接收者。主要缘故在于:1.指针接收者没有值拷贝带来的巨大开销。2.如果就想在函数中修改值就必须使用指针接收者。3.值接收者唯一的优势就是为了防止意外的修改,为了防止这一点可以通过创建一个函数或者技巧来手动 copy,而这并不会带来多大的开销。
易错点辨析
是否改变结构体的值看的是技巧是指针接收者还是值接收者,而不是看调用方是指针还是值。缘故在于golang编译器在背后会完成一些职业,比如:解引用,隐式使用引用。代码范例如下:
package mainimport “fmt”type Node struct val int}func (receiver Node) changeVal1() receiver.val++}func (receiver *Node) changeVal2() receiver.val++}func main() someOne := Node} someOne.changeVal1() fmt.Printf(“%dn”, someOne.val) //0 ,说明没有改值,由于技巧接收者是值接收者 someOnePtr := &Node} someOnePtr.changeVal1() fmt.Printf(“%dn”, someOnePtr.val) //0 ,说明没有改值,由于技巧接收者是值接收者,与调用方是否指针无关 someTwo := Node} someTwo.changeVal2() fmt.Printf(“%dn”, someTwo.val) //1 ,说明成功改值,由于技巧接收者是指针接收者,与调用方是否指针无关 someTwoPtr := &Node} someTwoPtr.changeVal2() fmt.Printf(“%dn”, someTwoPtr.val) //1 ,说明成功改值,由于技巧接收者是指针接收者,与调用方是否指针无关}
参考:https://golang.design/go-questions/interface/receiver/
到此这篇关于go 指针接收者和值接收者的区别的文章就介绍到这了,更多相关go 指针接收者和值接收者内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
无论兄弟们可能感兴趣的文章:
- golang接口实现调用修改(值接收者指针接收者)场景详解
- Go技巧接收者值接收者与指针接收者详解
- golang值接收者和指针接收者的区别介绍