GoLang嵌入式struct类层次结构

时间:2015-02-20 16:56:37

标签: go

我正在阅读此博文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()可以自行工作,但在通过接口调用时不起作用

2 个答案:

答案 0 :(得分:1)

您的callValueable(v Valueable)函数的参数类型为Valueable,这是一个接口:

type Valueable interface {
    Value() int64
}

您可以将任何值传递给实现此接口的任何值。您的Parent类型没有,因为即使它有Value()方法,该方法也有一个指针接收器:

func (i *Parent) Value() int64{
    return i.value
}

根据Go语言规范(Method setsInterface types),Parent的方法集不包括此方法,只包括*Parent的方法集。引用规范:

  

...任何其他类型T的方法集包含使用接收器类型T声明的所有方法。相应指针类型*T的方法集是使用接收方*TT声明的所有方法的集合(也就是说,它还包含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不会自动插入&对我们来说,因为它无法保证内存地址在整个函数调用生命周期中都是有效的。