【问题标题】: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 中,这是结构和类之间的根本区别,而像 GuidDateTime 这样的类型被故意实现为结构(值类型)。同样,我认为指针通常是更好的选择(如果您通过 .NET 查看几乎所有内容都是类,引用类型),但这绝对取决于您希望使用该类型实现什么和/或您希望消费者如何/其他开发人员与之交互。您可能需要考虑性能和并发性(也许您希望一切都是按值计算的,因此您不必担心类型上的并发操作,也许您需要一个指针,因为对象的内存占用很大并且复制它会使您程序太慢或消耗过多)。

【讨论】:

    【解决方案2】:

    看看来自the official FAQ的这个项目:

    对于不习惯使用指针的程序员来说, 这两个例子可能会令人困惑,但情况实际上是 很简单。当在一个类型上定义一个方法时,接收者(s in the 上面的例子)的行为就像它是一个参数 方法。将接收者定义为值还是指针 那么,同样的问题是,函数参数是否应该是 值或指针。有几个考虑因素。

    首先,也是最重要的,方法是否需要修改 接收者?如果是这样,接收者必须是一个指针。 (切片和地图 作为参考,所以他们的故事有点微妙,但对于 实例以更改接收方必须的方法中的切片长度 仍然是一个指针。)在上面的例子中,如果指针方法修改 s 的字段,调用者会看到这些变化,但 valueMethod 是 使用调用者参数的副本调用(这是 传递一个值),所以它所做的更改对调用者是不可见的。

    顺便说一句,指针接收器与Java中的情况相同, 尽管在 Java 中指针隐藏在幕后;这是围棋 不寻常的价值接收者。

    其次是效率的考虑。如果接收器很大,则 例如大结构,使用指针会便宜得多 接收器。

    接下来是一致性。如果该类型的某些方法必须有 指针接收器,其余的也应该,所以方法集是 无论类型如何使用都一致。请参阅关于 方法集了解详情。

    对于基本类型、切片和小型结构等类型,一个值 接收器非常便宜,所以除非方法的语义需要 一个指针,一个值接收者,高效清晰。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      • 2018-10-20
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多