那么内存布局意味着在Go中无法将[] T转换为[]界面?

时间:2015-03-13 06:36:23

标签: interface go language-design duck-typing memory-layout

所以我一直在阅读这两篇文章和这个答案

Cannot convert []string to []interface {}表示需要更改内存布局。

http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go表示理解底层记忆可以轻松回答这个问题,

http://research.swtch.com/interfaces,解释了幕后发生的事情。

但对于我的生活,我无法想到一个原因,就接口的实现而言,为什么[] T不能被强制转换为[]接口。

为什么?

2 个答案:

答案 0 :(得分:4)

文章" InterfaceSlice"试着详细说明:

  

类型为[]interface{}的变量不是接口!它是一个切片,其元素类型恰好是interface{}。但即使考虑到这一点,也许可以说意思很明确。

     好吧,是吗?类型为[]interface{}的变量具有特定的内存布局,在编译时已知。

     

每个interface{}占用两个单词(一个单词表示包含的内容,另一个单词表示包含的数据或指向它的指针)。因此,长度为N且类型为[]interface{}的切片由一长N * 2个字的数据块支持。

另见" what is the meaning of interface{} in golang?"

2 words

  

这与支持类型为[]MyType且长度相同的切片的数据块不同。它的数据块长N*sizeof(MyType)个字。

     

结果是您无法快速将[]MyType类型的内容分配给[]interface{}类型的内容;他们背后的数据看起来不同。

" why []string can not be converted to []interface{} in Go"增加了一个很好的例证:

// imagine this is possible
var sliceOfInterface = []interface{}(sliceOfStrings)
// since it's array of interface{} now - we can do anything
// let's put integer into the first position
sliceOfInterface[0] = 1
// sliceOfStrings still points to the same array, and now "one" is replaced by 1
fmt.Println(strings.ToUpper(sliceOfStrings[0])) // BANG!

答案 1 :(得分:1)

阅读博客文章The Laws of ReflectionThe representation of an interface部分。

  

接口类型的变量存储一对:赋给变量的具体值,以及该值的类型描述符。更确切地说,值是实现接口的基础具体数据项,类型描述该项的完整类型。

因此,如果您的值为[]TT的一片),其中T不是接口,则此类切片的元素仅存储类型{{1但它不存储类型信息,它属于切片类型。

如果您的值为T,则此类切片的元素将保存具体值这些值的类型描述符。

因此[]inteface{}中的元素需要比非接口[]interface{}更多的信息(更多内存)。如果这两个切片的占用内存不相同,那么它们就不能只是看着#34;不同(看作不同的类型)。从另一个生产一个需要额外的工作。