【问题标题】:Should I define my funcs with a pointer to the struct or just on the struct?我应该用指向结构的指针还是只在结构上定义我的函数?
【发布时间】:2016-07-01 09:25:53
【问题描述】:
在go中我似乎有两个选择:
foo := Thing{}
foo.bar()
foo := &Thing{}
foo.bar()
func (self Thing) bar() {
}
func (self *Thing) bar() {
}
用 self Thing 或 self *Thing 定义我的函数的更好方法是什么?
编辑:这不是关于方法和函数的问题的重复。这个问题与 Thing 和 &Thing 有关,我认为它的不同足以保证它自己的 url。
【问题讨论】:
标签:
pointers
go
function-pointers
【解决方案1】:
没有明确的答案,但它们完全不同。当您不使用指针时,您“按值传递”,这意味着您调用它的对象将是不可变的(修改副本),当您使用指针时,您“按引用传递”。我想说的是,您更经常使用指针变体,但它完全是根据情况而定的,没有“更好的方法”。
如果您查看各种编程框架/类库,您会看到许多示例,其中作者故意选择按值或引用来做事。例如,在 C# .NET 中,这是结构和类之间的根本区别,而像 Guid 和 DateTime 这样的类型被故意实现为结构(值类型)。同样,我认为指针通常是更好的选择(如果您通过 .NET 查看几乎所有内容都是类,引用类型),但这绝对取决于您希望使用该类型实现什么和/或您希望消费者如何/其他开发人员与之交互。您可能需要考虑性能和并发性(也许您希望一切都是按值计算的,因此您不必担心类型上的并发操作,也许您需要一个指针,因为对象的内存占用很大并且复制它会使您程序太慢或消耗过多)。
【解决方案2】:
看看来自the official FAQ的这个项目:
对于不习惯使用指针的程序员来说,
这两个例子可能会令人困惑,但情况实际上是
很简单。当在一个类型上定义一个方法时,接收者(s in the
上面的例子)的行为就像它是一个参数
方法。将接收者定义为值还是指针
那么,同样的问题是,函数参数是否应该是
值或指针。有几个考虑因素。
首先,也是最重要的,方法是否需要修改
接收者?如果是这样,接收者必须是一个指针。 (切片和地图
作为参考,所以他们的故事有点微妙,但对于
实例以更改接收方必须的方法中的切片长度
仍然是一个指针。)在上面的例子中,如果指针方法修改
s 的字段,调用者会看到这些变化,但 valueMethod 是
使用调用者参数的副本调用(这是
传递一个值),所以它所做的更改对调用者是不可见的。
顺便说一句,指针接收器与Java中的情况相同,
尽管在 Java 中指针隐藏在幕后;这是围棋
不寻常的价值接收者。
其次是效率的考虑。如果接收器很大,则
例如大结构,使用指针会便宜得多
接收器。
接下来是一致性。如果该类型的某些方法必须有
指针接收器,其余的也应该,所以方法集是
无论类型如何使用都一致。请参阅关于
方法集了解详情。
对于基本类型、切片和小型结构等类型,一个值
接收器非常便宜,所以除非方法的语义需要
一个指针,一个值接收者,高效清晰。