前言

可变参函数是指函数的某个参数可有可无,即这个参数个数可以是0个或多个。声明可变参数函数的方式是在参数类型前加上...前缀。

比如fmt包中的Println:

  1. func Println(a ...interface{})

本节我们会总结一下其使用方法,顺便了解一下其原理,以避免在使用过程中进入误区。

函数特征

我们先写一个可变参函数:

  1. func Greeting(prefix string, who ...string) {
  2. if who == nil {
  3. fmt.Printf("Nobody to say hi.")
  4. return
  5. }
  6. for _, people := range who{
  7. fmt.Printf("%s %s\n", prefix, people)
  8. }
  9. }

Greeting函数负责给指定的人打招呼,其参数who为可变参数。

这个函数几乎把可变参函数的特征全部表现出来了:

  • 可变参数必须在函数参数列表的尾部,即最后一个(如放前面会引起编译时歧义);
  • 可变参数在函数内部是作为切片来解析的;
  • 可变参数可以不填,不填时函数内部当成nil切片处理;
  • 可变参数必须是相同类型的(如果需要是不同类型的可以定义为interface{}类型);

使用举例

我们使用testing包中的Example函数来说明上面Greeting函数(函数位于sugar包中)用法。

不传值

调用可变参函数时,可变参部分是可以不传值的,例如:

  1. func ExampleGreetingWithoutParameter() {
  2. sugar.Greeting("nobody")
  3. // OutPut:
  4. // Nobody to say hi.
  5. }

这里没有传递第二个参数。可变参数不传递的话,默认为nil。

传递多个参数

调用可变参函数时,可变参数部分可以传递多个值,例如:

  1. func ExampleGreetingWithParameter() {
  2. sugar.Greeting("hello:", "Joe", "Anna", "Eileen")
  3. // OutPut:
  4. // hello: Joe
  5. // hello: Anna
  6. // hello: Eileen
  7. }

可变参数可以有多个。多个参数将会生成一个切片传入,函数内部按照切片来处理。

传递切片

调用可变参函数时,可变参数部分可以直接传递一个切片。参数部分需要使用slice...来表示切片。例如:

  1. func ExampleGreetingWithSlice() {
  2. guest := []string{"Joe", "Anna", "Eileen"}
  3. sugar.Greeting("hello:", guest...)
  4. // OutPut:
  5. // hello: Joe
  6. // hello: Anna
  7. // hello: Eileen
  8. }

此时需要注意的一点是,切片传入时不会生成新的切片,也就是说函数内部使用的切片与传入的切片共享相同的存储空间。说得再直白一点就是,如果函数内部修改了切片,可能会影响外部调用的函数。

总结

  • 可变参数必须要位于函数列表尾部;
  • 可变参数是被当作切片来处理的;
  • 函数调用时,可变参数可以不填;
  • 函数调用时,可变参数可以填入切片;

赠人玫瑰手留余香,如果觉得不错请给个赞~

本篇文章已归档到GitHub项目,求星~ 点我即达