什么时候应该在Go中定义值(而不是指针)的方法?

时间:2011-06-13 09:56:21

标签: go

已定义

type MyInt int

我想定义一个只打印值的方法.ShowMe()。我可以使用*MyInt

来定义它
func (this *MyInt) ShowMe() {
    fmt.Print(*this, "\n")
}

或使用MyInt

func (this MyInt) ShowMe() {
    fmt.Print(this, "\n")
}

在什么情况下建议在值上定义方法而不是指针?

2 个答案:

答案 0 :(得分:9)

做出这个决定时,有两个问题要问自己:

  1. 我是否希望能够修改接收者的价值?
  2. 复制接收者的价值会不会很贵?
  3. 如果这两个问题的答案都是肯定的,那么在指针上定义方法。

    在您的示例中,您不需要修改接收器的值,并且复制接收器并不昂贵。

    为了确定#2的答案,我的经验法则是:如果接收器是具有多个字段的结构,则通过指针传递。否则按值传递。

答案 1 :(得分:5)

Go FAQCC-licensed)有一个答案:

  

Should I define methods on values or pointers?

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

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

     

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

     

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

     

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

     

接下来是一致性。如果该类型的某些方法必须具有   指针接收器,其余的也应该是,所以方法集是   无论使用何种类型,都是一致的。见the section on method sets   详情。

     

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