可变参数函数是指函数参数的某个参数可有可无,即这个参数的个数可以为0会多个。可变参数函数参数在日常编程中大量使用,Go的可变参函数的声明就是在参数类型上假设加上”…”的前缀,这样的定义规则其实跟其他大多数编程语言的可变参数的定义是一样的。

接下来分情况讨论Go的可变参数函数的两种情景。

多个同类型的可变参数列表

多个同类型的函数可变参数列表的写法如下,注意可变参数列表必须放在函数参数的最后一个,不然会引发编译歧义。

  1. func Handle(v int, s ...string) {
  2. fmt.Println(v, s)
  3. }

我们在调用该函数时,不传递第二个参数并不会引发编译错误,当然也可以传递超过2个的参数,只有保证第二个之后的参数类型是string即可。下面看看这个例子:

  1. package main
  2. // main.go
  3. import (
  4. "fmt"
  5. )
  6. func Handle(v int, s ...string) {
  7. fmt.Println(v, s)
  8. }
  9. func main() {
  10. Handle(100)
  11. Handle(100, "hello")
  12. Handle(100, "hello", "world")
  13. }

输出如下,值得注意的是,可变参数列表实际就是个切片类型,我们可以不断地增加参数就是把参数往参数切片中塞数值。

  1. 100 []
  2. 100 [hello]
  3. 100 [hello world]

正因为可变参数是个切片类型,我们可以把我们的参数包装成切片,再将切片传入函数。不过需要注意,切片传入时不会生成新的切片,也就是函数内部使用的切片与传入的切片共享相同的存储空间。

  1. package main
  2. // main.go
  3. import (
  4. "fmt"
  5. )
  6. func Handle(v int, s ...string) {
  7. fmt.Println(v, s)
  8. }
  9. func main() {
  10. s := []string {"hello", "Go",}
  11. Handle(100, s...)
  12. }

输出:

  1. 100 [hello Go]

如果我们可变参数中传入了跟定义的可变参数列表类型不一样的数据,会编译错误。

  1. Handle(100, "hello", "world", 1)

那针对这种可变参数列表的数据类型不一致的情况该怎么解决呢?可以使用interface{}来处理。

多个不同类型的可变参数列表

针对可变参数列表中存在不同类型的参数的情况,我们可以使用interface{}空接口来解决,我们可以将可变参函数定义如下:

  1. func Handle(v int, s ...interface{}) {
  2. fmt.Println(v, s)
  3. }

对于上面的函数,我们可以往该函数传入各种类型的数据。一个例子如下:

  1. package main
  2. // main.go
  3. import (
  4. "fmt"
  5. )
  6. func Handle(v int, s ...interface{}) {
  7. fmt.Println(v, s)
  8. }
  9. func main() {
  10. m := map[string]int {
  11. "ID" :1,
  12. }
  13. Handle(100)
  14. Handle(100, "hello")
  15. Handle(100, "hello", "world")
  16. Handle(100, "hello", "world", 1)
  17. Handle(100, "hello", "world", 1, m)
  18. }

输出:

  1. 100 []
  2. 100 [hello]
  3. 100 [hello world]
  4. 100 [hello world 1]
  5. 100 [hello world 1 map[ID:1]]

总结

  1. 可变参数必须位于函数参数列表的尾部;
  2. 可变参数是当做切片来处理;
  3. 函数调用时,可变参数可以不填;
  4. 函数调用时,可变参数可以传入切片。