我正在阅读此博文http://www.hydrogen18.com/blog/golang-embedding.html,并遇到了这些内容
这里有一个重要的区别。如果myParent是Parent的实例,则myParent值不能作为Valueable。您必须使用值& myParent(指向实例的指针)充当Valueable。这是因为方法Value接收* Parent而不是Parent。
我创建了一个示例https://play.golang.org/p/ojTKZfx97g。所以问题是为什么调用方法 myparent.Value()可以自行工作,但在通过接口调用时不起作用
答案 0 :(得分:1)
您的callValueable(v Valueable)
函数的参数类型为Valueable
,这是一个接口:
type Valueable interface {
Value() int64
}
您可以将任何值传递给实现此接口的任何值。您的Parent
类型没有,因为即使它有Value()
方法,该方法也有一个指针接收器:
func (i *Parent) Value() int64{
return i.value
}
根据Go语言规范(Method sets和Interface types),Parent
的方法集不包括此方法,只包括*Parent
的方法集。引用规范:
...任何其他类型
T
的方法集包含使用接收器类型T
声明的所有方法。相应指针类型*T
的方法集是使用接收方*T
或T
声明的所有方法的集合(也就是说,它还包含T
的方法集)
因此类型Parent
未实现Valueable
接口,但类型*Parent
确实实现了它。
因此,您可以将*Parent
(一个指针到Parent
)作为Valuable
值传递给您的方法,因为它实现了接口。您可以使用地址&
运算符
fmt.Println(callValueable(&myparent)) // This WORKS
答案 1 :(得分:1)
根据生效,如果值可寻址,则go将自动插入&在调用指针接收器方法时。
我对此做了进一步的研究,看起来我的理解可寻址是错误的。我在思考c ++这一行,而只要它是左值,那么它就是可寻址的。但似乎在golang中并不是所有东西都可以解决,例如
然后有趣的问题是为什么具体类型的接口不可寻址,以便golang可以自动执行&amp ;.我找到了https://groups.google.com/forum/#!topic/golang-nuts/-ZoCu5m0kJ4。我引用了Steven Blenkinsop的答案,你可以在最后找到答案
在一个层面上,这是因为语言规范是这样说的。但最终,是的,这是因为获取指针作为接收器传递的限制。您不能获取接口内的值的地址,因为其类型可能会更改(您可以为接口分配不同类型的值),以及其他原因。因此,如果需要指针接收器,则指针本身需要位于接口中。
所以我看到界面或地图的方式,因为底层内存地址可能会改变另一个线程,这就是为什么go不会自动插入&对我们来说,因为它无法保证内存地址在整个函数调用生命周期中都是有效的。