为什么不能在go中传递`func()[] int`作为`func()[] interface {}`?

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:

  1. 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.

  2. 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.