当前位置: 首页 > 后端技术 > PHP

你知道Gostruct和指向struct调用的指针之间的区别吗?

时间:2023-03-30 00:49:19 PHP

微信搜索【脑补炸鱼】关注这条炸肝炸鱼。本文GitHubgithub.com/eddycjy/blog已收录,附有我的系列文章、资料和开源Go书籍。大家好,我是炸鱼。前几天分享《Go 结构体是否可以比较,为什么?》的时候,有朋友提了一个新问题:虽然大家提问的速度已经超过了写文章的速度……但是作为狂鱼粉,清明期间还是要去做的假期。写了这篇文章。上网搜索相关问题,发现Go开发者在6年前就有过一模一样的问题,着实困扰了几代朋友。本期主人公是《Go 结构体和结构体指针调用有什么区别》,希望对大家有所帮助,带来一些思考。请先把心中的答案读到这里,再和建宇讨论一波围棋的技术哲学。什么是结构?Go语言中有一种基本类型,开发者称之为结构体(struct)。在Go语言中很常用,基本定义:typestruct_variable_typestruct{memberdefinitionmemberdefinition...memberdefinition}简单例子:packagemainimport"fmt"typeVertexstruct{Name1stringName2string}funcmain(){v:=Vertex{"脑子在","炸鱼"}v.Name2="清蒸鱼"fmt.Println(v.Name2)}输出结果:清蒸鱼部分属于基础知识,就不做了'不多解释了。如果不明白,建议重新学习Go语言语法基础知识。结构体和指针调用前面小结讲解完毕,直接进入本文正题。以下示例:typeMyStructstruct{Namestring}func(sMyStruct)SetName1(namestring){s.Name=name}func(s*MyStruct)SetName2(namestring){s.Name=name}User结构体,其中包含两个结构体方法,分别是SetName1和SetName2方法,两者的区别在于引用方式。进一步延伸,这两者有什么区别,在什么情况下使用哪一种,有什么注意事项吗?注:巧合的是,我有一个朋友在刚开始接触Go语言的时候也被这个问题困扰过。两者的区别从很多小伙伴的反馈来看,这两个例子的区别可能会让人迷惑。人们经常纠结于是否使用“指针”或担心GC。其实并没有那么复杂,看下面的例子:s)的行为就好像它是方法的参数一样。等价于:funcSetName1(sMyStruct,namestring){u.Name=name}funcSetName2(s*MyStruct,namestring){u.Name=name}所以结构体方法就是定义接收者为一个值,或指针。这与函数参数应该是值还是指针本质上是同一个问题。如何选择整体有以下几点考虑,按重要性排序:使用中的注意事项:方法是否需要修改receiver?如果需要,接收器必须是指针。效率方面的考虑:如果接收者很大,比如一个很大的结构体,那么使用指针接收者会好很多。一致性方面的考虑:如果一个类型的某些方法必须有指针接收者,那么其余的方法也应该有指针接收者,所以无论该类型如何使用,方法集都是一致的。回到上面的例子,从功能使用的角度来看:如果SetName2方法修改了s的字段,调用者可以看到这些字段值的变化,因为它们都是指针引用,本质上是一样的.与SetName1方法相反,此方法是使用调用方参数的副本调用的,并且本质上是按值传递的,它所做的任何字段更改对调用方都是不可见的。此外,对于基元、切片和小型结构等类型,值接收器的成本非常低。所以除非方法的语义需要指针,否则值接收者是最有效和清晰的。GC方面,无需过多关注。当它出现时修复它。总结在这篇文章中,我们对Go结构体和结构体指针调用的区别进行了深入的分析和解释。并且本文介绍的部分内容来自官方FAQ《ShouldIdefinemethodsonvaluesorpointers?》,也算是官方给出的基本答案(问的人还真多)。谁对这个问题有疑问,转发这篇文章,就完了。如有任何问题,欢迎在评论区反馈交流。最好的关系是相互成就。您的好评是创作炸鱼最大的动力。感谢您的支持。文章持续更新中,微信搜索【脑补炸鱼】即可阅读,回复【000】一线大厂面试算法方案和资料我都准备好了;本文已收录在GitHubgithub.com/eddycjy/blog,欢迎Star提醒。