Why can't I pass a `func() []int` as `func() []interface{}` in go?

断了今生、忘了曾经 提交于 2019-12-13 22:53:24

问题


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

回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/49640390/why-cant-i-pass-a-func-int-as-func-interface-in-go

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!