【问题标题】:Golang method receiverGolang 方法接收器
【发布时间】:2017-01-11 01:27:36
【问题描述】:

根据this question,golang会同时生成type-receiver methodpoint-receiver method,也就是说下面的代码可以正常运行,值会发生意外变化。

func (test *Test) modify() {
    test.a++
}

func main() {
    test := Test{10}
    fmt.Println(test)
    test.modify()
    fmt.Println(test)
}

我认为这对我来说是可以接受的。但是当它与界面混合时,事情就出错了。

type Modifiable interface {
    modify()
}

type Test struct {
    a int
}

func (test *Test) modify() {
    test.a++
}

func main() {
    test := Test{10}
    fmt.Println(test)
    test.modify()
    fmt.Println(test)

    var a Modifiable

    a = test
}

它说:

Test does not implement Modifiable (modify method has pointer receiver)

为什么会这样?

以及 golang 实际是如何处理方法调用的?

【问题讨论】:

    标签: go interface


    【解决方案1】:

    当你说:

    func (test *Test) modify() {
        test.a++
    }
    

    这意味着接口Modifiable*Test 类型实现,也就是指向测试的指针

    在哪里

    func (test Test) modify() {
            test.a++
    }
    

    表示接口由Test类型实现

    结论是:类型和指向该类型的指针是两种不同的类型。

    【讨论】:

    • 但是test 变量确实有一个名为modify 的方法,我可以通过test.modify() 调用,为什么它说Test does not implement Modifiable
    • 因为你在*Test而不是Test上实现了接口。 modify 方法是为 *Test 定义的,而不是为 Test 类型定义的。当您调用test.modify 时,编译器将自动传递*Test,但从接口实现的角度来看,您需要显式使用*Test
    • 所以给定链接中的答案是错误的,Test 的方法没有生成?编译器真正做的是将指针传递给pointer-method,而不是调用不存在的生成方法。
    • 是的,没有生成任何方法。查看tour.golang.org/methods/6tour.golang.org/methods/7
    • 非常感谢。 @Ankur
    【解决方案2】:

    如果您想使用具有指针接收器的方法。这意味着您必须传递地址值。

    这是一个例子:

    package main
    
    import "fmt"
    
    type Modifiable interface {
        modify()
    }
    
    type Test struct {
        a int
    }
    
    func (test *Test) modify() {
        test.a++
    }
    
    func main() {
        test := Test{10}
        fmt.Println(test)
        test.modify()
        fmt.Println(test)
    
        var a Modifiable
    
        a = &test
        a.modify()
        fmt.Println(a)
    }
    

    总之,只要您在方法中创建指针接收器,接口就会接受地址值。

    【讨论】:

      猜你喜欢
      • 2014-07-30
      • 1970-01-01
      • 2017-11-08
      • 2016-02-29
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 2015-06-11
      • 2021-12-07
      相关资源
      最近更新 更多