patterngoCritical
Type converting slices of interfaces
Viewed 0 times
slicestypeinterfacesconverting
Problem
I'm curious why Go does't implicitly convert
Example:
cannot use a (type []string) as type []interface {} in function argument
And if I try to do it explicitly, same thing:
cannot convert a (type []string) to type []interface {}
So every time I need to do this conversion (which seems to come up a lot), I've been doing something like this:
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.
[]T to []interface{} when it will implicitly convert T to interface{}. Is there something non-trivial about this conversion that I'm missing? Example:
func foo([]interface{}) { /* do something */ }
func main() {
var a []string = []string{"hello", "world"}
foo(a)
}go build complains cannot use a (type []string) as type []interface {} in function argument
And if I try to do it explicitly, same thing:
b := []interface{}(a) complains cannot convert a (type []string) to type []interface {}
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]
}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.
Solution
In Go, there is a general rule that syntax should not hide complex/costly operations.
Converting a
The one exception to this rule is converting strings. When converting a
There is no standard library function that will do this conversion for you. Your best option though is just to use the lines of code you gave in your question:
Otherwise, you could make one with
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{}.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. 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]
}Otherwise, you could make one with
reflect, but it would be slower than the three line option. Example with reflection:func InterfaceSlice(slice interface{}) []interface{} {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
// Keep the distinction between nil and empty slice input
if s.IsNil() {
return nil
}
ret := make([]interface{}, s.Len())
for i:=0; i<s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret
}Code Snippets
b := make([]interface{}, len(a))
for i := range a {
b[i] = a[i]
}func InterfaceSlice(slice interface{}) []interface{} {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
// Keep the distinction between nil and empty slice input
if s.IsNil() {
return nil
}
ret := make([]interface{}, s.Len())
for i:=0; i<s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret
}Context
Stack Overflow Q#12753805, score: 345
Revisions (0)
No revisions yet.