Go 打开切片的包装

Go 打开切片的包装,go,slice,variadic-functions,Go,Slice,Variadic Functions,我很好奇如何将一片切片解包并将它们作为参数发送给一个变量函数 假设我们有一个可变参数的函数: func unpack(args ...interface{}) 如果我们不想传入一个接口片段,它就可以工作,那么解包与否无关紧要: slice := []interface{}{1,2,3} unpack(slice) // works unpack(slice...) // works 如果我们有一片一片的话,事情就变得棘手了。在这里,编译器不允许我们传入未打包的版本: sliceOfSlice

我很好奇如何将一片切片解包并将它们作为参数发送给一个变量函数

假设我们有一个可变参数的函数:

func unpack(args ...interface{})
如果我们不想传入一个接口片段,它就可以工作,那么解包与否无关紧要:

slice := []interface{}{1,2,3}
unpack(slice) // works
unpack(slice...) // works
如果我们有一片一片的话,事情就变得棘手了。在这里,编译器不允许我们传入未打包的版本:

sliceOfSlices := [][]interface{}{
    []interface{}{1,2},
    []interface{}{101,102},
}
unpack(sliceOfSlices) // works
unpack(sliceOfSlices...) // compiler error
错误显示:

无法将切片(类型[][]接口{})用作参数中的类型[]接口{}来解包

我不知道为什么会发生这种情况,因为我们可以清楚地将
[]接口{}
类型传递到函数中。如何使用
sliceOfSlices
的解包内容作为参数调用解包方法

操场示例:

这在以下章节中介绍:

如果
f
是可变的,且最后一个参数
p
类型为
…T
,则
f
p
的类型等同于类型
[]T

如果最后一个参数可分配给切片类型
[]T
,则如果该参数后跟
..T
参数,则可以将其作为
..T
参数的值不变地传递。在这种情况下,不会创建新切片

简而言之:这是一个编译时错误,因为不能将
切片
(类型为
[]interface{}
)分配给
args
(类型为
[]interface{}

长:

在您执行
unpack(slice)
的第一个示例中,由于
unpack()
需要
interface{}
的值,因此
slice
(类型为
[]interface{}
)将被包装在一个新的
interface{}
值中,并将作为单个参数传递

当您执行
unpack(slice…
时,这将把
slice
的所有值作为单独的值传递给
unpack()
;这是可能的,因为
切片的类型是
[]接口{}
,它与可变参数的类型匹配(
args…接口{}

在第二个示例中,当您执行
unpack(sliceOfSlices)
时,
sliceOfSlices
将被包装在一个新的
接口{}
值中,并作为单个参数传递

但是当您尝试
unpack(sliceOfSlices…
)时,会希望将
sliceOfSlices的每个元素传递给
unpack()
,但是
sliceOfSlices的类型(即
[]]接口{}
)与可变参数的类型不匹配,因此出现编译时错误

切片
传递到
解包()
“分解”的唯一方法是创建一个类型必须为
[]接口{}
的新切片,复制元素,然后可以使用
..
传递它

例如:

var sliceOfSlices2 []interface{}
for _, v := range sliceOfSlices {
    sliceOfSlices2 = append(sliceOfSlices2, v)
}

unpack(sliceOfSlices2...)
试穿一下

让我们使用以下
unpack()
函数来验证参数的数量:

func unpack(args ...interface{}) {
    fmt.Println(len(args))
}
运行您的示例(并使用我的新切片创建),输出为:

1
3
1
2
在没有
..
的情况下,只传递一个参数(包装在
接口{}
中),并且使用
..
将分别传递所有元素

在计算机上尝试此测试