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?
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.
This question is related to
go
go-reflect
go-interface
Convert interface{}
into any type.
Syntax:
result := interface.(datatype)
Example:
var employee interface{} = []string{"Jhon", "Arya"}
result := employee.([]string) //result type is []string.
The thing you are missing is that T
and interface{}
which holds a value of T
have different representations in memory so can't be trivially converted.
A variable of type T
is just its value in memory. There is no associated type information (in Go every variable has a single type known at compile time not at run time). It is represented in memory like this:
An interface{}
holding a variable of type T
is represented in memory like this
T
So coming back to your original question: why go does't implicitly convert []T
to []interface{}
?
Converting []T
to []interface{}
would involve creating a new slice of interface {}
values which is a non-trivial operation since the in-memory layout is completely different.
In case you need more shorting your code, you can creating new type for helper
type Strings []string
func (ss Strings) ToInterfaceSlice() []interface{} {
iface := make([]interface{}, len(ss))
for i := range ss {
iface[i] = ss[i]
}
return iface
}
then
a := []strings{"a", "b", "c", "d"}
sliceIFace := Strings(a).ToInterfaceSlice()
Here is the official explanation: 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
}
Try interface{}
instead. To cast back as slice, try
func foo(bar interface{}) {
s := bar.([]string)
// ...
}
Source: Stackoverflow.com