【问题标题】:Golang method with pointer receiver [duplicate]带有指针接收器的Golang方法[重复]
【发布时间】:2016-02-29 09:33:41
【问题描述】:

我有这个示例代码

package main

import (
    "fmt"
)

type IFace interface {
    SetSomeField(newValue string)
    GetSomeField() string
}

type Implementation struct {
    someField string
}

func (i Implementation) GetSomeField() string {
    return i.someField
}

func (i Implementation) SetSomeField(newValue string) {
    i.someField = newValue
}

func Create() IFace {
    obj := Implementation{someField: "Hello"}
    return obj // <= Offending line
}

func main() {
    a := Create()
    a.SetSomeField("World")
    fmt.Println(a.GetSomeField())
}

SetSomeField 无法按预期工作,因为它的接收者不是指针类型。

如果我将方法更改为指针接收器,我希望它可以工作,它看起来像这样:

func (i *Implementation) SetSomeField(newValue string) { ...

编译它会导致以下错误:

prog.go:26: cannot use obj (type Implementation) as type IFace in return argument:
Implementation does not implement IFace (GetSomeField method has pointer receiver)

如何让struct 实现接口方法SetSomeField 更改实际实例的值而不创建副本?

这是一个可破解的 sn-p: https://play.golang.org/p/ghW0mk0IuU

我已经看过这个问题In go (golang), how can you cast an interface pointer into a struct pointer?,但我看不出它与这个例子有什么关系。

【问题讨论】:

    标签: go


    【解决方案1】:

    指向结构的指针应该实现接口。这样你就可以修改它的字段了。

    看看我是如何修改你的代码,让它按你期望的那样工作:

    package main
    
    import (
        "fmt"
    )
    
    type IFace interface {
        SetSomeField(newValue string)
        GetSomeField() string
    }
    
    type Implementation struct {
        someField string
    }    
    
    func (i *Implementation) GetSomeField() string {
        return i.someField
    }
    
    func (i *Implementation) SetSomeField(newValue string) {
        i.someField = newValue
    }
    
    func Create() *Implementation {
        return &Implementation{someField: "Hello"}
    }
    
    func main() {
        var a IFace
        a = Create()
        a.SetSomeField("World")
        fmt.Println(a.GetSomeField())
    }
    

    【讨论】:

      【解决方案2】:

      简单的答案是,当SetSomeField 以您想要的方式工作时,您将无法让结构实现您的接口。

      但是,指向结构的指针将实现接口,因此将您的 Create 方法更改为 return &amp;obj 应该可以正常工作。

      根本问题是您修改后的SetSomeField 方法不再在Implementation 的方法集中。虽然*Implementation 类型将继承非指针接收器方法,但反之则不然。

      原因与接口变量的指定方式有关:访问存储在接口变量中的动态值的唯一方法是复制它。例如,想象一下:

      var impl Implementation
      var iface IFace = &impl
      

      在这种情况下,对iface.SetSomeField 的调用有效,因为它可以复制指针以用作方法调用中的接收者。如果我们直接在接口变量中存储一个结构,我们需要创建一个指向该结构的指针来完成方法调用。一旦创建了这样的指针,就可以访问(并可能修改)接口变量的动态值,而无需复制它。

      【讨论】:

      • 感谢詹姆斯的分享!我想这应该是公认的答案,因为它提供了接口内部和结构的指针接收器方法的更详细的答案。
      • “如果我们直接在接口变量中存储一个结构,我们需要创建一个指向该结构的指针来完成方法调用。” - 实际上不是真的。这是一个例子:play.golang.org/p/v3Rl3l0MKZ7
      • @UdayHiwarale:您的示例不包含接口变量。看到这个错误:play.golang.org/p/0ABWJlxC_oQ
      猜你喜欢
      • 2014-07-30
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-30
      • 1970-01-01
      • 2018-09-30
      • 2013-08-02
      相关资源
      最近更新 更多