我有以下定义:
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
答案 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{}
«在记忆中的表现形式相同»。
要明白原因,让我们分析两件事:
切片是后备存储array加上包含大小和容量的几个整数 切片。
在Go中,数组不是某种“高级”;反之, 它们包含的元素的布局是严格定义的:它们都是 包含在一个连续的记忆区域,彼此相邻。
这意味着,在切片[]T
的后备数组中,元素是
键入T
,并且每个类型都占用大小自然的内存区域
对于该类型T
,所有这些区域都彼此相邻
在一个连续的内存块中。
这意味着,片[]int
的每个元素恰好占用64位
(8字节)在64位平台上 - 单个int
值的内存量
占据。
任何接口类型的值,包括空接口,
interface{}
表示为包含两个指针的结构,
类似的东西:
type iface struct {
realType *typeInfo
realValue *dataType
}
(更多关于如何表示界面 - here)。
所有上述方法都在切片[]interface{}
中每个元素占据
内存区域有两个指针的大小,而这两个指针包含
内存中其他变量的地址 - 而不仅仅是整数值
由[]int
的元素包含。
反过来,这意味着您不能仅仅将[]int
“投射到”[]interface{}
- 只是因为存储在[]int
的任何元素中的值(int
1}})
与元素的结构(内存布局)不兼容
[]interface{}
(包含两个指针的结构)。
要从另一个生成一个,您需要分配一个切片并转换每个切片
源切片的元素到目标的匹配元素。
最后,这意味着如果函数返回类型为[]int
的切片,
该切片不能由期望切片的代码直接处理
键入[]interface{}
(反之亦然),这就解释了原因
您问题中的两个函数签名表示不兼容
类型。