我很好奇拆包切片并将其作为参数发送给可变参数函数。
假设我们有一个带有可变参数的函数:
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(类型[] [] interface {})用作类型[] interface {}
我不知道为什么会这样,因为我们可以清楚地将[]interface{}
类型传递给函数。如何用sliceOfSlices
as参数的解压缩内容调用解压缩方法?
游乐场示例:https :
//play.golang.org/p/O3AYba8h4i
规范中对此进行了介绍:将参数传递给…
parameters
:
如果
f
为带有最终p
类型为type的可变参数...T
,则f
类型内p
等于type[]T
。…
如果最终参数可分配给切片类型
[]T
,...T
则在参数后跟时可以将其作为参数的值原样传递...
。在这种情况下,不会创建新的切片。
因此,在短期:
这是一个编译时错误,因为sliceOfSlices
(这是类型的[][]interface{}
)不能被分配到args
(这是类型[]interface{}
)(上游乐场证明)。
总而言之:
在第一个示例中,当您执行时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()
“爆炸”
的唯一方法是创建一个新切片,其类型必须为[]interface{}
,复制元素,然后可以使用传递它...
。
例:
var sliceOfSlices2 []interface{}
for _, v := range 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上尝试此测试。
取一个list或tuple的部分元素是非常常见的操作。比如,一个list如下: >>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack'] 取前3个元素,应该怎么做? 笨办法: >>> [L[0], L[1], L[2]] ['Michael', 'Sarah', 'Tracy'] 之所以是笨办法是因为扩展一下,取前N个元素就没辙了。 取前N个元素
举个例子 给你一个list 让你取前30个怎么办? a = [] # 很多数据 a[0],a[1] #按照这种方式吗?这也太复杂了! for i in a: pass ## 这种方式也是可以的,但是还是有点复杂了,在编程语言中,或者是我们的编程思想中,less is more是最重要的,也就是说,写的越少越好。 # 所以我们可以采用切片的方式 a[1:3],从第二个开始到第
取一个list或tuple的部分元素是非常常见的操作。比如,一个list如下: >>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack'] 取前3个元素,应该怎么做? 笨办法: >>> [L[0], L[1], L[2]] ['Michael', 'Sarah', 'Tracy'] 之所以是笨办法是因为扩展一下,取前N个元素就没辙了。 取前N个元素
在Go中,和之间有什么区别? 我发现两者都有效,但哪一个更好?
切片是Go语言的关键类型之一,它提供了比数组更多的功能。 示例1: package main import "fmt" func main() { // 和数组不同的是,切片的长度是可变的。 // 我们可以使用内置函数make来创建一个长度不为零的切片 // 这里我们创建了一个长度为3,存储字符串的切片,切片元素 // 默认为零值,对于字符串就是""。 s
7.2.1 概念 切片(slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型,或者 Python 中的 list 类型)。这个片段可以是整个数组,或者是由起始和终止索引标识的一些项的子集。需要注意的是,终止索引标识的项不包括在切片内。切片提供了一个相关数组的动态窗口。 切片是可索引的,并且可以由 len()