可变参函数的深度理解:
函数接收的参数数目都是确定的。而可变参数函数的参数数目是不确定的
如果一个函数的最后一个参数的表示形如:…Type,则该参数(形参)可以接受不同数目的参数(实参)
func f(elems ...Type)
需要注意的一点,只允许最后一个参数是可变参数
Go 中的一些内置函数都是可变参数函数:
例如:append()函数:
func append(slice []Type, elems ...Type) []Type
s := []int{1,2,3}
s = append(s,4,5,6,7,8)
elems就是可变参数,可以接收任意数目的实参
可变参的原理:
func test(str1 string, s ...string) {
fmt.Println(str1)
fmt.Printf("%T\n",s) // %T 输出变量类型
fmt.Println(s)
}
func main() {
str:= "net"
test(str,"Hello","World","Go")
}
//输出:
net
[]string
[Hello World Go]
test()函数中,参数s是[]string类型的切片
可变参数函数的工作原理就是把可变参数转化成切片
调用test()函数时可变参数是Hello、World、Go,这三个参数被编译器转化成切片[]string{“Hello”,“World”,“Go”} ,然后被传入test()函数
另外,调用test()函数时候,可以不传可变参数,在 Go 语言里也是合法的,这种情况下,s是一个长度和容量都是 0 的 nil 切片
将切片传递给可变参数函数
func test(str1 string, s ...string) {
fmt.Println(str1)
fmt.Printf("%T\n",s)
fmt.Println(s)
}
func main() {
slice := []string{"Hello","World","Go"}
str := "net"
test(str,slice)
}
将切片slice传给可变参数函数test(),结果编译出错:
cannot use slice (type []string) as type string in argument to
由可变参数函数的定义可知,s …string 意味它可以接受 string 类型的可变参数。slice作为可变参数传入test()函数。前面我们知道,可变参数会被转换为 string 类型切片然后再传入test()函数中。但slice是一个 string 类型的切片,编译器试图通过下面这种方式在slice基础上再创建一个切片
test("net", []string{s})
之所以会失败,因为slice是[]string类型,而不是string类型
解决方法:
Go 提供了将切片传入可变参数函数的语法糖:
直接在切片后加上…后缀。这样,切片将直接传入函数,不会再创建新的切片
test(blog,slice...)
//输出:
net
[]string
[Hello World Go]
如果在函数中改变切片的值会发生什么呢?
func test(s ...string) {
s[0] = "net"
fmt.Printf("%T\n",s)
fmt.Println(s)
}
func main() {
slice := []string{"Hello","World","Go"}
test(slice...)
fmt.Println(slice)
}
//输出:
[]string
[net World Go]
[net World Go]
使用了...,切片本身会作为参数直接传入,不会再创建一个新的切片。
所以在test()函数中,第一个元素被替换成 net,会影响到main()函数的切片
可以通过将数组转化成切片传递给可变参数函数:
func test(s ...string) {
s[0] = "net"
fmt.Printf("%T\n",s)
fmt.Println(s)
}
func main() {
arr := [3]string{"Hello","World","Go"}
test(arr[:]...)
fmt.Println(arr)
}