Unpacking slice of slices

让人想犯罪 __ 提交于 2019-12-01 08:33:19

This is covered in Spec: Passing arguments to ... parameters:

If f is variadic with a final parameter p of type ...T, then within f the type of p 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.

So in short: it is a compile-time error because sliceOfSlices (which is of type [][]interface{}) cannot be assigned to args (which is of type []interface{}) (proof on Playground).

In long:

In your first example when you do unpack(slice), since unpack() expects values of interface{}, therefore slice (which is of type []interface{}) will be wrapped in a new interface{} value, and it will be passed as a single argument.

When you do unpack(slice...), this will pass all the values of slice as separate values to unpack(); this is possible because type of slice is []interface{}, it matches the type of the variadic parameter (args ...interface{}).

In your second example when you do unpack(sliceOfSlices), again, sliceOfSlices will be wrapped in a new interface{} value and passed as a single argument.

But when you try unpack(sliceOfSlices...), that would want to pass each element of sliceOfSlices to unpack(), but type of sliceOfSlices (which is [][]interface{}) does not match the type of the variadic parameter, hence the compile-time error.

The only way to pass sliceOfSlices to unpack() "exploded" is to create a new slice whose type must be []interface{}, copy the elements, then you can pass it using ....

Example:

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

unpack(sliceOfSlices2...)

Try it on the Go Playground.

Let's use the following unpack() function to verify the number of arguments:

func unpack(args ...interface{}) {
    fmt.Println(len(args))
}

Running your example (and with my new slice creation), output is:

1
3
1
2

Which proves without ... only a single argument is passed (wrapped in interface{}), and using ... all elements will be passed separately.

Try this test on the Go Playground.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!