指针上定义的方法仍可使用值调用

时间:2014-08-13 02:52:04

标签: go

“Effective Go”文档说明如下。

  

有关接收器的指针与值的规则是可以在指针和值上调用值方法,但只能在指针上调用指针方法。

http://tip.golang.org/doc/effective_go.html#pointers_vs_values

因此,如果我定义一个类似下面的方法,它不能用值来调用吗?

func (self *someStruct) Change(newNum int) {
    self.propertyOne = newNum
}

但是,以下似乎仍有效。

structInstance := &someStruct{
    propertyOne: 41,
}
(*structInstance).Change(456)

为什么?

是否将值(*structInstance)转换回Change来电的地址/指针?

如何确保某个类型的实例无法调用指针上定义的方法(如Change)?

去游乐场演示

http://play.golang.org/p/azbpp_djlG

2 个答案:

答案 0 :(得分:2)

当在指针接收器上定义函数时,Go会自动将值转换为该函数的指针。

type Cookies struct {
    Num int
}

func (c *Cookies) Buy(n int) {
    c.Num += n
}

func main() {
    c := Cookies{}
    c.Buy(10) //is equal to (&c).Buy(10)
    fmt.Println(c)
}

我无法找到现在定义的位置的引用,但我知道它在规范中的某个官方文档中。

另外请注意,请不要在Go中使用selfthis

//修改

来自http://tip.golang.org/ref/spec#Calls

  

如果方法集x(类型)x包含m并且参数列表可以分配给m的参数列表,则方法调用x.m()有效。 如果x是可寻址的且& x的方法集包含m,则x.m()是(& x).m()

的缩写

答案 1 :(得分:1)

来自the language specification

  

如果方法集{(1)}的x.m()包含x并且参数列表可以分配给{{1}的参数列表,则方法调用m有效}。如果m可寻址且x的方法集包含&x,则mx.m()

的简写

在您的示例中,(&x).m()的方法集中没有Change方法,但它是可寻址的,并且该方法存在于(*structInstance)的方法集中,因此调用是解释为&(*structInstance),或更简单地(&(*structInstance)).Change(456)

防止此行为的唯一方法是在structInstance.Change(456)上定义Change方法,也许会让人感到恐慌。但这并不理想,因为它只会告诉你运行时的问题。构建程序不那么令人困惑,因此使用这种速记实际上并不重要。