如果我有以下结构的实例
type Node struct {
id string
name string
address string
conn net.Conn
enc json.Encoder
dec json.Decoder
in chan *Command
out chan *Command
clients map[string]ClientNodesContainer
}
我无法理解何时应该通过引用发送结构,何时应该按值发送它(考虑到我不想对该实例进行任何更改),是否有一个经验法则可以使它更容易决定?
所有我能找到的是当它的小或便宜复制时按值发送一个结构,但是小的真的意味着小于64位地址吗?
如果有人可以指出一些更明显的规则,会很高兴
答案 0 :(得分:10)
规则很简单:
没有概念"通过引用传递/发送"在Go中,你所能做的只是传递价值。
关于是否传递结构的值或指向结构的指针的问题(这不是通过引用调用的!):
所有这些都在考虑复制费用是多少浪费时间。副本很便宜,即使是中型结构也是如此。在分析后,传递指针可能是一个合适的优化。
你的结构不大。大型结构包含wholeWorldBuf [1000000]uint64
等字段。
像你这样的微小结构可能会或可能不会从传递指针中获益,而任何提供更好的建议的人都在说谎:这完全取决于你的代码和通话模式。
如果你没有合理的选项和分析显示复制你的结构花费时间:尝试使用指针。
答案 1 :(得分:2)
&#34>的原则通常会传递你不打算变异的小结构的值。我同意,但是这个结构现在在x64上是688字节,大多数是嵌入式json
结构中的结构。细分是:
net.Conn
(接口值)json.Encoder
json.Decoder
Here's我以前使用的代码,虽然您需要在本地保存它以运行它,因为它使用unsafe.Sizeof
。
您可以嵌入*Encoder
/ *Decoder
而不是指针,只需104字节。不过,我认为保持现状并通过*Node
是合理的。
接收器类型上的转到code review comments说"有多大?假设它相当于将所有元素作为参数传递给方法。如果感觉太大,对接收器来说也太大了。"这里有不同意见的空间,但对我来说,九个值,一些多个单词,"感觉很大"甚至在获得精确数字之前。
在"Pass Values" section审核评论文档中说"此建议不适用于大型结构,甚至可能适用于可能增长的小结构。"它没有说"大"相同的标准。适用于接收器的正常参数,但我认为这是一种合理的方法。
在代码审查文档中提到的确定大小的部分细节是,Go中的许多内容都是内部指针或包含引用的小结构:切片(但不是固定大小的数组),字符串,{{ 1}}值,函数值,通道,映射。你的struct可能拥有一个指向64KB缓冲区的interface
,或者通过[]byte
拥有一个大结构,但复制起来仍然很便宜。我在另一个答案中wrote some about this,但我在那里所说的一切都无法阻止人们做出一些不那么科学的判断。
看看标准库方法的作用很有意思。 bytes.Replace
有十个单词'值得args,所以至少有时可以复制到堆栈上。另一方面,go/ast
倾向于传递引用(interface
指针或接口值),即使对于非巨大结构上的非变异方法也是如此。结论:很难将它简化为几个简单的规则。 :)
答案 2 :(得分:-1)
大多数时候你应该使用传递参考。像:
func (n *Node) exampleFunc() {
...
}
只有当您希望使用按值传递实例时,才能确保您的实例不会发生更改。