为什么要定义值而不是指针的方法?

时间:2014-03-14 13:35:38

标签: go

查看示例Go代码,有些事情并不一致。许多代码在指针类型上定义它们的方法,例如:

func (p *parser) parse () {...}

但是其他一些代码只在类型上定义方法,而不是指向它的指针:

func (s scanner) scan () {...}

有充分的理由做后者吗?通过值而不是指针传递对象真的更有效吗?

一个原因是“我无法更改此对象”,但无论如何这都是大对象的问题(您是否会通过值传递大结构以标记它无法通过方法更改?)

2 个答案:

答案 0 :(得分:5)

幸运的是,这是Go FAQ

  

我应该在值或指针上定义方法吗?

func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct)  valueMethod()   { } // method on value`
     

对于不习惯指针的程序员来说,区别   这两个例子可能令人困惑,但事实上情况确实如此   非常简单。在类型上定义方法时,接收器(在   上面的例子)就像它是一个参数一样   方法。是将接收器定义为值还是指针   同样的问题,那么,函数参数是否应该是a   值或指针。有几点需要考虑。

     

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

     

顺便说一句,指针接收器与Java中的情况相同,   虽然在Java中,指针隐藏在封面下;这是Go的   价值接收器是不寻常的。

     

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

     

接下来是一致性。如果该类型的某些方法必须具有   指针接收器,其余的也应该是,所以方法集是   无论使用何种类型,都是一致的。请参阅有关的部分   方法设置细节。

     

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

所以是的,它主要用于语义。在处理并发时,知道方法是无副作用的是一件好事,因为这自动意味着不需要锁定。除了全局变量和引用类型之外,值接收器强烈暗示您的方法没有副作用。

答案 1 :(得分:0)

方法链也是一个考虑因素。如果你想写的话

one.Two().Three()

然后Two()需要返回一个指针,或者Three()需要有一个值接收器,因为方法调用的结果不是addressable。如果Two返回一个值,则无法获取其地址以便在其上调用指针接收方法。但是,如果Three()具有值接收器,则无论Two()是否返回指针,它都将起作用。