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

时间:2018-04-03 23:13:08

标签: go interface

我有以下定义:

func (c *Collector) RegisterSource(f func() []interface{}) {
    c.source = f
}

我尝试按如下方式调用它,但出现错误:

func source() []int {
    return []int{ 0, 1, 2, 3, 4 }
}
...
c.RegisterSource(source)

这符合:

cannot use source (type func() []int) as type func() []interface {} in argument to c.RegisterSource

2 个答案:

答案 0 :(得分:2)

因为[] int和[]接口是2种不同类型的切片而且go不允许在2之间自动转换。

https://github.com/golang/go/wiki/InterfaceSlice

你所能做的就是改变这个

func source() []int {
    return []int{ 0, 1, 2, 3, 4 }
}

进入那个

func source() []interface{} {
    return []interface{}{ 0, 1, 2, 3, 4 }
}

以适合您为RegisterSource定义的函数签名。

答案 1 :(得分:2)

relevant Go FAQ entry表示[]T[]interface{}«在记忆中的表现形式相同»。

要明白原因,让我们分析两件事:

  1. 切片是后备存储array加上包含大小和容量的几个整数 切片。

    在Go中,数组不是某种“高级”;反之, 它们包含的元素的布局是严格定义的:它们都是 包含在一个连续的记忆区域,彼此相邻。

    这意味着,在切片[]T的后备数组中,元素是 键入T,并且每个类型都占用大小自然的内存区域 对于该类型T,所有这些区域都彼此相邻 在一个连续的内存块中。

    这意味着,片[]int的每个元素恰好占用64位 (8字节)在64位平台上 - 单个int值的内存量 占据。

  2. 任何接口类型的值,包括空接口, interface{}表示为包含两个指针的结构, 类似的东西:

    type iface struct {
        realType  *typeInfo
        realValue *dataType
    }
    

    (更多关于如何表示界面 - here)。

  3. 所有上述方法都在切片[]interface{}中每个元素占据 内存区域有两个指针的大小,而这两个指针包含 内存中其他变量的地址 - 而不仅仅是整数值 由[]int的元素包含。

    反过来,这意味着您不能仅仅将[]int“投射到”[]interface{} - 只是因为存储在[]int的任何元素中的值(int 1}}) 与元素的结构(内存布局)不兼容 []interface{}(包含两个指针的结构)。 要从另一个生成一个,您需要分配一个切片并转换每个切片 源切片的元素到目标的匹配元素。

    最后,这意味着如果函数返回类型为[]int的切片, 该切片不能由期望切片的代码直接处理 键入[]interface{}(反之亦然),这就解释了原因 您问题中的两个函数签名表示不兼容 类型。