为了账号安全,请及时绑定邮箱和手机立即绑定

内存布局意味着[]T不能在Go中转换为[]接口?

内存布局意味着[]T不能在Go中转换为[]接口?

Go
浮云间 2021-09-21 16:19:20
所以我一直在阅读这两篇文章和这个答案无法将 []string 转换为 []interface {}表示需要更改内存布局。http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go说了解底层内存使回答这个问题变得容易,并且http://research.swtch.com/interfaces,解释了幕后发生的事情。但是对于我的生活,我想不出一个原因,就接口的实现而言,为什么 []T 不能转换为 []interface。所以为什么?
查看完整描述

2 回答

?
繁星淼淼

TA贡献1775条经验 获得超11个赞

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

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

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

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

//img1.sycdn.imooc.com//6149960b00016c6904870238.jpg

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


结果是您无法快速将 type 分配给[]MyTypetype []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!


查看完整回答
反对 回复 2021-09-21
?
holdtom

TA贡献1805条经验 获得超10个赞

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

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

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

如果您有一个 type 值[]inteface{},则此类切片的元素包含这些值的具体值类型描述符。

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


查看完整回答
反对 回复 2021-09-21
  • 2 回答
  • 0 关注
  • 218 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信