- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我很好奇解包 slice 并将它们作为参数发送给可变参数函数。
假设我们有一个带有可变参数的函数:
func unpack(args ...interface{})
如果我们不想传入它工作的接口(interface)片段,我们是否解压它并不重要:
slice := []interface{}{1,2,3}
unpack(slice) // works
unpack(slice...) // works
如果我们有一片 slice ,它会变得棘手。这里编译器不允许我们传入解压后的版本:
sliceOfSlices := [][]interface{}{
[]interface{}{1,2},
[]interface{}{101,102},
}
unpack(sliceOfSlices) // works
unpack(sliceOfSlices...) // compiler error
错误说:
cannot use sliceOfSlices (type [][]interface {}) as type []interface {} in argument to unpack
我不知道为什么会这样,因为我们可以清楚地将 []interface{}
类型传递到函数中。如何以 sliceOfSlices
的解压内容作为参数调用 unpack 方法?
Playground 示例:https://play.golang.org/p/O3AYba8h4i
最佳答案
这包含在 Spec: Passing arguments to ... parameters 中:
If
f
is variadic with a final parameterp
of type...T
, then withinf
the type ofp
is equivalent to type[]T
....
If the final argument is assignable to a slice type
[]T
, it may be passed unchanged as the value for a...T
parameter if the argument is followed by...
. In this case no new slice is created.
简而言之:这是一个编译时错误,因为 sliceOfSlices
(类型为 [][]interface{}
)不能分配给 args
(类型为 []interface{}
)(proof on Playground)。
长:
在您执行 unpack(slice)
时的第一个示例中,由于 unpack()
需要 interface{}
的值,因此 slice
(属于 []interface{}
类型)将被包裹在一个新 interface{}
值中,并且它将作为一个单个参数传递。
当你执行 unpack(slice...)
时,这会将 slice
的所有值作为单独的值传递给 unpack()
;这是可能的,因为 slice
的类型是 []interface{}
,它匹配可变参数的类型 (args ...interface{}
>).
在第二个示例中,当您执行 unpack(sliceOfSlices)
时,sliceOfSlices
将再次包装在一个新 接口(interface){ }
值并作为单个参数传递。
但是当你尝试 unpack(sliceOfSlices...)
时,它会想要将 sliceOfSlices
的每个元素传递给 unpack()
,但是 sliceOfSlices
的类型(即 [][]interface{}
)与可变参数的类型不匹配,因此出现编译时错误。
将 sliceOfSlices
传递给 unpack()
“exploded” 的唯一方法是创建一个新的 slice ,其类型必须是 []interface{}
code>,复制元素,然后你可以使用...
传递它。
例子:
var sliceOfSlices2 []interface{}
for _, v := range sliceOfSlices {
sliceOfSlices2 = append(sliceOfSlices2, v)
}
unpack(sliceOfSlices2...)
在 Go Playground 上试试.
让我们使用下面的 unpack()
函数来验证参数的数量:
func unpack(args ...interface{}) {
fmt.Println(len(args))
}
运行您的示例(以及我创建的新 slice ),输出为:
1
3
1
2
这证明没有 ...
只传递了一个参数(包装在 interface{}
中),并且使用 ...
所有元素将单独传递。
在 Go Playground 上尝试这个测试.
关于go - slice slice 的拆包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39914447/
我是一名优秀的程序员,十分优秀!