带指针接收器的Golang方法

Atm*_*ons 37 go

我有这个示例代码

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())
}
Run Code Online (Sandbox Code Playgroud)

SetSomeField 不能正常工作,因为它的接收器不是指针类型.

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

func (i *Implementation) SetSomeField(newValue string) { ...
Run Code Online (Sandbox Code Playgroud)

编译它会导致以下错误:

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

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

这是一个可以破解的片段:https: //play.golang.org/p/ghW0mk0IuU

我已经看过这个问题在go(golang)中,如何将接口指针转换为结构指针?,但我看不出它与这个例子有什么关系.

nes*_*uno 46

指向结构的指针应该实现接口.通过这种方式,您可以修改其字段.

看看我如何修改你的代码,使它按预期工作:

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())
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*dge 23

简单的答案是,SetSomeField在按照您想要的方式工作时,您将无法使结构实现您的界面.

但是,指向struct的指针将实现接口,因此更改要执行的Create方法return &obj应该可以实现.

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

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

var impl Implementation
var iface IFace = &impl
Run Code Online (Sandbox Code Playgroud)

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

  • 感谢詹姆斯的分享!我猜这应该是可以接受的答案,因为它提供了接口内部和struct的指针接收器方法的更详细的答案。 (2认同)