问题描述
我很好奇为什么Go不会将T
隐式转换为interface{}
时不将[]T
隐式转换为[]interface{}
.我缺少这种转换的重要内容吗?
I'm curious why Go does't implicitly convert []T
to []interface{}
when it will implicitly convert T
to interface{}
. Is there something non-trivial about this conversion that I'm missing?
示例:
func foo([]interface{}) { /* do something */ }
func main() {
var a []string = []string{"hello", "world"}
foo(a)
}
go build
抱怨
如果我尝试显式地执行此操作,则同样的事情:b := []interface{}(a)
抱怨
And if I try to do it explicitly, same thing: b := []interface{}(a)
complains
因此,每次我需要进行这种转换(这似乎很多)时,我一直在做这样的事情:
So every time I need to do this conversion (which seems to come up a lot), I've been doing something like this:
b = make([]interface{}, len(a), len(a))
for i := range a {
b[i] = a[i]
}
是否有更好的方法或标准库函数来帮助进行这些转换?每次我想调用一个可以列出例如以下内容的函数时,多写4行代码似乎有点愚蠢.整数或字符串.
Is there a better way to do this, or standard library functions to help with these conversions? It seems kind of silly to write 4 extra lines of code every time I want to call a function that can take a list of e.g. ints or strings.
推荐答案
在Go中,有一个通用规则,即语法不应隐藏复杂/昂贵的操作.将string
转换为interface{}
的时间为O(1).由于切片仍然是一个值,因此也要在O(1)时间内将[]string
转换为interface{}
.但是,将[]string
转换为[]interface{}
的时间为O(n),因为切片的每个元素都必须转换为interface{}
.
In Go, there is a general rule that syntax should not hide complex/costly operations. Converting a string
to an interface{}
is done in O(1) time. Converting a []string
to an interface{}
is also done in O(1) time since a slice is still one value. However, converting a []string
to an []interface{}
is O(n) time because each element of the slice must be converted to an interface{}
.
此规则的一个例外是转换字符串.在将string
与[]byte
或[]rune
之间相互转换时,即使转换是语法",Go仍可以执行O(n).
The one exception to this rule is converting strings. When converting a string
to and from a []byte
or a []rune
, Go does O(n) work even though conversions are "syntax".
没有标准的库函数可以为您完成此转换.您可以使用反射来制作一个,但是它比三行选项要慢.
There is no standard library function that will do this conversion for you. You could make one with reflect, but it would be slower than the three line option.
带有反射的示例:
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
}
您最好的选择只是使用问题中给出的代码行:
Your best option though is just to use the lines of code you gave in your question:
b := make([]interface{}, len(a))
for i := range a {
b[i] = a[i]
}
这篇关于接口切片的类型转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!