开包切片 [英] Unpacking slice of slices

查看:192
本文介绍了开包切片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



比方说,我们有一个带可变参数的函数:

  func unpack(args ... interface {})

如果我们不想传入它的一部分接口,那么解开它还是不要紧。

  slice:= [] interface {} {1,2,3} 
解包(切片)//作品
解包(切片...)/ / works

如果我们有一片切片,这会变得棘手。在这里,编译器不让我们传入一个解压缩版本:

  sliceOfSlices:= [] [] interface {} {
[] interface {} {1,2},
[] interface {} {101,102},
}
unpack(sliceOfSlices)//工程
解包(sliceOfSlices ...)//编译器错误

错误提示:
$


无法使用sliceOfSlices(type [] [] interface {})作为参数中的类型[] interface {}解包


我不知道为什么会发生这种情况,因为我们可以清楚地将 [] interface {} 类型传递给函数。我怎样才能用 sliceOfSlices 的解压内容作为参数来调用解压方法?



Playground示例: https://play.golang.org/p/O3AYba8h4i

解决方案

规范:将参数传递给...参数


如果 f 是可变参数,并带有最终参数> ... 类型的code> p ,然后在 f 类型 p 相当于类型 [] T



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


简而言之:由于 sliceOfSlices (其类型为 [] [] interface {}),因此是编译时错误。 )不能被分配给 args (它的类型为 [] interface {} )) (操场上的证明)。





在你的第一个例子中,当你做 unpack(slice)时,因为 unpack()期望接口{} 的值,因此 slice (它的类型为 [] interface {} )将被封装在新的 接口{}中。 code> value,它会作为一个单独的参数传递。



当你执行 unpack( slice ...),它会将 slice 的所有值作为单独值传递给 unpack();这是可能的,因为 slice 的类型是 [] interface {} ,它匹配variadic参数的类型( args ... interface {} )。



在第二个例子中,当你做 (sliceOfSlices),再次, sliceOfSlices 将被封装在新的 界面{} 值并作为单个参数传递。



但是,当您尝试解包(sliceOfSlices。 ..),那就是要将 sliceOfSlices 的每个元素传递给 unpack() ,但类型 sliceOfSlices (它是 [] [] interface {} )与可变参数的类型不匹配参数,因此编译时错误。



sliceOfSlices 传递给 unpack()exploded是创建一个类型必须为 [] interface {} 的新片段,复制元素,然后可以传递它使用 ...



示例:

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

unpack(sliceOfSlices2 ...)

Go Playground



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

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

运行您的示例(并使用我的新切片创建),输出为:

  1 
3
1
2

证明没有。 .. 只传递一个参数(包装在 interface {} 中),并使用 ... 所有元素将分开传递。



请在 Go Playground


I am curious about unpacking a slice of slices and sending them as arguments to a variadic function.

Let's say we have a function with variadic parameters:

func unpack(args ...interface{})

If we wan't to pass in a slice of interfaces it works, it doesn't matter if we unpack it or not:

slice := []interface{}{1,2,3}
unpack(slice) // works
unpack(slice...) // works

It gets tricky if we have a slice of slices. Here the compiler doesn't let us pass in an unpacked version:

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

The error says:

cannot use sliceOfSlices (type [][]interface {}) as type []interface {} in argument to unpack

I don't know why this happens, as we can clearly pass an []interface{} type into the function. How can I call the method unpack with the unpacked content of sliceOfSlices as arguments?

Playground example: https://play.golang.org/p/O3AYba8h4i

解决方案

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.

这篇关于开包切片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆