在go中键入转换接口片

我很好奇,为什么go不会隐式地把T转换为[]interface{}当它隐式地将T转换为interface{} 。 有没有什么不重要的转换,我失踪了?

例:

 func foo([]interface{}) { /* do something */ } func main() { var a []string = []string{"hello", "world"} foo(a) } 

go build抱怨

在函数参数中不能使用(type [] string)作为type [] interface {}

如果我试图明确地做,同样的事情: b := []interface{}(a)抱怨

无法将(type []string)转换为键入[] interface {}

所以每次我需要做这个转换(这似乎出现了很多),我一直在做这样的事情:

 b = make([]interface{}, len(a), len(a)) for i := range a { b[i] = a[i] } 

有没有更好的方法来做到这一点,或标准库函数来帮助这些转换? 每次我想调用一个函数,例如整数或string的列表时,编写4行额外的代码似乎是很愚蠢的。

在Go中,通常的规则是语法不应该隐藏复杂/昂贵的操作。 将string转换为interface{}在O(1)时间内完成。 将[]string转换为interface{}也是在O(1)时间内完成的,因为切片仍然是一个值。 但是,将[]string转换为[]interface{}是O(n),因为切片的每个元素必须转换为interface{}

这个规则的一个例外是转换string。 当将string转换为[]byte[]rune ,即使转换为“语法”,Go也会运行O(n)。

没有标准的库函数会为你做这个转换。 你可以做一个反映,但它会比三线选项慢。

reflection示例:

 func InterfaceSlice(slice interface{}) []interface{} { s := reflect.ValueOf(slice) if s.Kind() != reflect.Slice { panic("InterfaceSlice() given a non-slice type") } ret := make([]interface{}, s.Len()) for i:=0; i<s.Len(); i++ { ret[i] = s.Index(i).Interface() } return ret } 

尽pipe你最好的select只是使用你在你的问题中给出的代码行:

 b := make([]interface{}, len(a)) for i := range a { b[i] = a[i] } 

你缺less的东西是Tinterface{} ,它保存了一个值T在内存中有不同的表示,所以不能被简单地转换。

Ttypes的variables在内存中只是其值。 没有关联的types信息(在Go中每个variables都有一个在编译时已知的types,而不是在运行时)。 像这样在记忆中performance出来

一个保存Ttypesvariables的interface{}就像这样在内存中表示

  • 指向typesT指针

所以回到你原来的问题:为什么不会隐式地将[]T转换为[]interface{}

[]T转换为[]interface{}将涉及创build一个新的interface {}值,这是一个不平凡的操作,因为内存布局是完全不同的。

这里是官方的解释: https : //github.com/golang/go/wiki/InterfaceSlice

 var dataSlice []int = foo() var interfaceSlice []interface{} = make([]interface{}, len(dataSlice)) for i, d := range dataSlice { interfaceSlice[i] = d } 

尝试使用interface{} 。 要退后一步,试试

 func foo(bar interface{}) { s := bar.([]string) // ... }