我有这个示例代码
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的指针来完成方法调用.一旦生成了这样的指针,就可以访问(并可能修改)接口变量的动态值而无需复制它.