I have the following definition:
func (c *Collector) RegisterSource(f func() []interface{}) {
c.source = f
}
I attempt to call it as follows but get an error:
func source() []int {
return []int{ 0, 1, 2, 3, 4 }
}
...
c.RegisterSource(source)
This is met with:
cannot use source (type func() []int) as type func() []interface {} in argument to c.RegisterSource
The relevant Go FAQ entry states that []T
and []interface{}
«do not have the same representation in memory».
To understand why, let's dissect two things:
A slice is a backing storage array plus several integers containing the size and capacity of the slice.
In Go, arrays are not somehow "high-level"; on the contrary, the layout of the elements they contain is strictly defined: they are all contained in a contiguous region of memory, adjacent to each other.
This means, that in the backing array of a slice []T
, elements are of type T
, and each of them occupies a region of memory of a size natural for that type T
, and all these regions are all adjacent to each other in a single contiguous memory block.
That means, each element of a slice []int
occupies exactly 64 bits (8 bytes) on a 64-bit platform — the amount of memory a single int
value occupies.
A value of any interface type, including the empty interface, interface{}
, is represented as a structure containing two pointers, something like:
type iface struct {
realType *typeInfo
realValue *dataType
}
(More on how interfaces are represented — here).
All of the above means in a slice []interface{}
each element occupies the region of memory the size of two pointers, and these two pointers contain addresses of other variables in memory — as opposed to mere integer values contained by elements of []int
.
And this, in turn, means you can't just "cast" []int
"to" []interface{}
— simply because a value stored in any element of []int
(an int
) is incompatible in its structure (memory layout) with an element of []interface{}
(a struct containing two pointers). To produce one from another, you need to allocate a slice and convert each element of the source slice to a matching element of the destination one.
Finally, this means if a function returns a slice of type []int
, that slice cannot be directly processed by code expecting slices of type []interface{}
(and vice-versa), and this explains why the two function signatures from your question represent incompatible types.
Because []int and []interface are 2 different types of slices and go does not allow automatic conversion between the 2.
https://github.com/golang/go/wiki/InterfaceSlice
all you can do is change this
func source() []int {
return []int{ 0, 1, 2, 3, 4 }
}
into that
func source() []interface{} {
return []interface{}{ 0, 1, 2, 3, 4 }
}
in order to fit the function signature you defined for RegisterSource
.