What about memory layout means that []T cannot be converted to []interface in Go?

huangapple go评论87阅读模式
英文:

What about memory layout means that []T cannot be converted to []interface in Go?

问题

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

https://stackoverflow.com/questions/12990338/cannot-convert-string-to-interface 说需要改变内存布局。

http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go 说了理解底层内存会让回答这个问题变得容易,以及

http://research.swtch.com/interfaces 解释了底层发生了什么。

但是,就我而言,我无法想出一个关于接口实现的原因,解释为什么 []T 不能转换为 []interface。

所以为什么呢?

英文:

So I've been reading these two articles and this answer

https://stackoverflow.com/questions/12990338/cannot-convert-string-to-interface says that the memory layout needs to be changed.

http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go says that understanding the underlying memory makes answering this question easy, and

http://research.swtch.com/interfaces, explains what is going on under the hood.

But for the life of me I can't think of a reason, in terms of the implementation of interfaces as to why []T cannot be cast to []interface.

So Why?

答案1

得分: 4

文章《InterfaceSlice》试图详细说明:

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

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

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

参见《在golang中interface{}的含义是什么?》

What about memory layout means that []T cannot be converted to []interface in Go?

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

结果是,你不能快速地将类型为[]MyType的东西赋值给类型为[]interface{}的东西;它们背后的数据看起来是不同的。

《为什么Go中[]string不能转换为[]interface{}》添加了一个很好的例子:

// 假设这是可能的
var sliceOfInterface = []interface{}(sliceOfStrings)
// 由于现在是interface{}的数组 - 我们可以做任何事情
// 让我们将整数放在第一个位置
sliceOfInterface[0] = 1
// sliceOfStrings仍然指向同一个数组,现在"one"被1替换了
fmt.Println(strings.ToUpper(sliceOfStrings[0])) // BANG!
英文:

The article "InterfaceSlice" try to detail:

> A variable with type []interface{} is not an interface! It is a slice whose element type happens to be interface{}. But even given this, one might say that the meaning is clear.
>
> Well, is it? A variable with type []interface{} has a specific memory layout, known at compile time.
>
> Each interface{} takes up two words (one word for the type of what is contained, the other word for either the contained data or a pointer to it). As a consequence, a slice with length N and with type []interface{} is backed by a chunk of data that is N*2 words long.

See also "what is the meaning of interface{} in golang?"

What about memory layout means that []T cannot be converted to []interface in Go?

> This is different than the chunk of data backing a slice with type []MyType and the same length. Its chunk of data will be N*sizeof(MyType) words long.
>
> The result is that you cannot quickly assign something of type []MyType to something of type []interface{}; the data behind them just look different.

"why []string can not be converted to []interface{} in Go" adds a good illustration:

// 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!

答案2

得分: 1

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

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

因此,如果你有一个类型为[]TT不是接口)的值,这样一个切片的元素只存储类型为T的值,但它不存储类型信息,它属于切片类型。

如果你有一个类型为[]interface{}的值,这样一个切片的元素既包含具体值,也包含这些值的类型描述符。

因此,[]interface{}中的元素需要更多的信息(更多的内存)比非接口类型的[]T。如果这两个切片所占用的内存不相同,它们不能仅仅被“不同地看待”(被看作不同的类型)。从一个转换为另一个需要额外的工作。

英文:

Read the blog article The Laws of Reflection, section The representation of an interface.

> A variable of interface type stores a pair: the concrete value assigned to the variable, and that value's type descriptor. To be more precise, the value is the underlying concrete data item that implements the interface and the type describes the full type of that item.

So if you have a value of []T (a slice of T) where T is not an interface, the elements of such a slice only stores values of type T, but it does not store the type information, it belongs to the slice type.

If you have a value of type []inteface{}, the elements of such a slice holds the concrete values and the type descriptors of those values.

So elements in a []interface{} require more info (more memory) than in a non-interface []T. And if the occupied memory of those 2 slices are not the same, they cannot be just "looked at" differently (looked at as a differnet type). Producing one from the other requires additional work.

huangapple
  • 本文由 发表于 2015年3月13日 14:36:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/29026241.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定