前天同事提起了一个例子,关于 Golang 中可变参数的使用,平时使用时没有注意这个细节,先上代码吧。
想要实现的代码逻辑很明了
1. TestArgs 接受一个 int 参数,一个不定长的参数,并且类型为 interface{}
2. nums 做为 slice,使用 ... 语法糖打散后传入 TestArgs
看上去逻辑没问题,执行报错
# command-line-arguments
./test.go:13: cannot use nums (type []int64) as type []interface {} in argument to TestArgs
居然报类型不匹配,写 Go 也一年了,这块的认知太不到位,一直认为会将 nums 打散,再以 interface{} 这个通用类型组成 interface{} slice 传到 TestArgs。
那么,我们看看到底 nums 传进去后是什么:
再执行后输出 []interface {},那么确认是把可变参数当做 slice 传给函数,这点和 python 很像。那我们再看看 slice 是不是同一个
执行后输出如下
main addr of slice 0xc82000c0c0
TestArgs addr of slice 0xc82000c0c0
地址相同,原来如果传入的可变参数本身就是由 slice 以 ... 形式传入的,那么就直接使用这个 slice,不会新建 slice。那么我理解的 Go 的可变参数执行方式:
对于 func(first int, arg ...T)
1. 当不传可变参数时,对应的 arg 就是 nil
2. 传入单个可变参数时,实际上执行 [] T{arg1,arg2,arg3}
3. 传入...语法糖的 slice时,直接使用这个 slice
由此我们就很好理解开篇的小例子为什么执行不了,[]int64 和 []interface{} 是两个类型的 slice 。