go - 范围指针的 Golang
问题描述
我是 Golang 的新手,最近遇到了与此问题中描述的相同的问题:奇怪的 golang "append" behavior
所以我想知道在for range
循环范围之外的任何地方使用循环中的对象副本是否基本上是不合适的——比如将它传递给一个单独的函数、附加它(如问题中所述)等等。
如果您计划对其进行变异,将其添加到该循环范围之外的列表等等,访问这样的对象几乎总是更合适,因为在下一个循环中您添加的指针会改变?
for index := range myList {
doSomething(&myList[index])
}
解决方案
您最需要记住的是 Go 是按值传递的。如果您完全可以使用副本,完全理解突变不会反映,并且巨大结构的副本可能很昂贵,那么传递副本或指针是完全正当的理由。
如果您需要进行修改,请按照此处显示的方式通过引用传递,或者您也可以将它们作为指针存储在切片中以以 eg 开头[]*MyStruct
。实际上,这揭示了他们在规范中专门选择通过复制传递结构的设计选择。
在幕后,aslice
抽象了一个数组,但只是一个结构,称为切片头,带有指向数组的指针。当你传递一个 slice 时,header 是通过value传递的,但内容基本上由 3 个整数组成,因此复制它并不昂贵。这就是在使用 append 时必须重新分配变量以使其持久存在的原因,例如s = append(s, value)
. 您可以通过引用在代码中传递切片,但这样做不是惯用的 Go。
推荐阅读
- spacy - spacy 模型不将街道名称识别为实体
- angular - [karma-server]:TypeError:无法读取未定义的属性“范围”-CI 环境中的 Angular 单元测试
- sql-server - 为 SQL Server 版本 8.00.760 模拟 sql Server ROW_COUNT()
- docker - 以线程安全的方式运行多个 docker 容器实例
- c# - T-SQL insert into 有时无法随机添加到表中
- javascript - 在自定义钩子中使用钩子时触发的钩子错误使用无效?
- c - 如何将字符串与子字符串进行比较以将第一个和第二个之间的相等部分转换为'*'而不使用
- node.js - 仅在一台服务器上测试 discord bot discordjs
- eclipse - 为什么我不能将本地 GitHub 存储库添加到 Eclipse 中?
- mongodb - MongoDB Atlas 未出现在 Azure 数据工厂 2 的链接服务列表中