1

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

无法将 []string 转换为 []interface {}表示需要更改内存布局。

http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go说理解底层内存可以很容易地回答这个问题,并且

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

但是对于我的生活,我想不出一个原因,就接口的实现而言,为什么 []T 不能转换为 []interface。

所以为什么?

4

2 回答 2

4

文章“ InterfaceSlice ”尝试详细说明:

具有类型的变量[]interface{}不是接口!它是一个元素类型恰好是 的切片interface{}。但即便如此,人们可能会说意思很清楚。

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

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

另请参阅“ golang中的含义是什么interface{}? ”

2 个字

这与支持具有类型[]MyType和相同长度的切片的数据块不同。它的数据块将是N*sizeof(MyType)单词长。

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

为什么[]string不能[]interface{}在 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!
于 2015-03-13T06:53:59.607 回答
1

阅读博客文章反射定律,接口的表示部分。

接口类型的变量存储一对:分配给变量的具体值,以及该值的类型描述符。更准确地说,值是实现接口的底层具体数据项,类型描述了该项的完整类型。

所以如果你有一个不是接口的[]T(a slice of T)的值,那么这样一个 slice 的元素只存储 type 的值,但它不存储类型信息,它属于 slice 类型。TT

如果你有一个 type 的值[]inteface{},那么这样一个 slice 的元素会保存具体的值这些值的类型描述符。

因此, a 中的元素[]interface{}比 non-interface 中的元素需要更多信息(更多内存)[]T。如果这 2 个 slice 的占用内存不相同,则它们不能只是以不同的方式“看待”(视为不同的类型)。从另一个生产一个需要额外的工作。

于 2015-03-13T06:55:29.090 回答