lma*_*gon 4 variadic-functions go slice
我很好奇解压缩切片并将它们作为参数发送到可变参数函数.
假设我们有一个带可变参数的函数:
func unpack(args ...interface{})
Run Code Online (Sandbox Code Playgroud)
如果我们不想传递它所使用的接口片段,那么如果我们解压缩它并不重要:
slice := []interface{}{1,2,3}
unpack(slice) // works
unpack(slice...) // works
Run Code Online (Sandbox Code Playgroud)
如果我们有一片切片,它会变得棘手.这里编译器不允许我们传入一个解压缩版本:
sliceOfSlices := [][]interface{}{
[]interface{}{1,2},
[]interface{}{101,102},
}
unpack(sliceOfSlices) // works
unpack(sliceOfSlices...) // compiler error
Run Code Online (Sandbox Code Playgroud)
错误说:
不能使用sliceOfSlices(type [] [] interface {})作为类型[] interface {}在解压缩的参数中
我不知道为什么会发生这种情况,因为我们可以清楚地将一个[]interface{}
类型传递给函数.如何使用aspacked内容sliceOfSlices
作为参数调用方法解压缩?
这是覆盖在规格:将参数传递给...参数:
如果
f
是具有p
类型的最终参数的可变参数...T
,则在f
类型内p
等效于类型[]T
....
如果最终参数可分配给切片类型
[]T
,则可以将其作为...T
参数的值(如果参数后跟参数)保持不变...
.在这种情况下,不会创建新切片.
所以简而言之:它是一个编译时错误,因为sliceOfSlices
(属于类型[][]interface{}
)无法分配args
(类型[]interface{}
)(Playground上的证明).
长期:
在你的第一个例子中unpack(slice)
,因为unpack()
期望值(interface{}
因此slice
类型[]interface{}
)将被包装在一个新 interface{}
值中,并且它将作为单个参数传递.
当你这样做时unpack(slice...)
,这会将所有值slice
作为单独的值传递给unpack()
; 这是可能的,因为类型slice
是[]interface{}
,它匹配variadic参数(args ...interface{}
)的类型.
在你的第二个例子中,当你这样做unpack(sliceOfSlices)
时,sliceOfSlices
将再次包装一个新 interface{}
值并作为单个参数传递.
但是当你尝试unpack(sliceOfSlices...)
,是想要通过的每一个元素sliceOfSlices
来unpack()
,但类型sliceOfSlices
(这是[][]interface{}
)不匹配一个可变参数的类型,因此编译时错误.
传递sliceOfSlices
给unpack()
"爆炸" 的唯一方法是创建一个新的切片,其类型必须是[]interface{}
,复制元素,然后您可以使用它...
.
例:
var sliceOfSlices2 []interface{}
for _, v := range sliceOfSlices {
sliceOfSlices2 = append(sliceOfSlices2, v)
}
unpack(sliceOfSlices2...)
Run Code Online (Sandbox Code Playgroud)
在Go Playground尝试一下.
让我们使用以下unpack()
函数来验证参数的数量:
func unpack(args ...interface{}) {
fmt.Println(len(args))
}
Run Code Online (Sandbox Code Playgroud)
运行您的示例(并使用我的新切片创建),输出为:
1
3
1
2
Run Code Online (Sandbox Code Playgroud)
这证明...
不仅传递一个参数(包装interface{}
),并且使用...
所有元素将分别传递.
在Go Playground上试试这个测试.
归档时间: |
|
查看次数: |
390 次 |
最近记录: |