【问题标题】:Method defined on pointer still callable with value在指针上定义的方法仍然可以用值调用
【发布时间】:2014-08-13 02:52:04
【问题描述】:

“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

【问题讨论】:

    标签: go


    【解决方案1】:

    当在指针接收器上定义函数时,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 的(类型)的方法集包含 m 并且参数列表可以分配给 m 的参数列表,则方法调用 x.m() 是有效的。 如果 x 是可寻址的并且 &x 的方法集包含 m,则 x.m() 是 (&x).m() 的简写

    【讨论】:

    • 快速搜索了一下,什么都想不出来,但是为什么在写 Go 的时候要避免 selfthis
    • 哦,这只是编码风格,大多数人都避免使用它。
    • @Deity from this by the Dave Cheney 本人,如果你使用这个或自己,你会被围棋之神不悦。
    • @Deity 它在the style guide
    • 啊,我明白了。感谢您的链接!我不知道有 Go wiki。
    【解决方案2】:

    来自the language specification

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

    在你的例子中,(*structInstance)的方法集中没有Change方法,但是它是可寻址的,并且该方法存在于&(*structInstance)的方法集中,所以调用被解释为(&(*structInstance)).Change(456),或者更简单的structInstance.Change(456)

    防止这种行为的唯一方法是在someStruct 上定义Change 方法,这可能会使其恐慌。但这并不理想,因为它只会在运行时告诉您问题。构建你的程序会不会那么混乱,这样使用这个速记实际上并不重要。

    【讨论】:

      猜你喜欢
      • 2016-09-24
      • 1970-01-01
      • 1970-01-01
      • 2012-10-23
      • 1970-01-01
      • 2012-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多