046-变长参数函数(Variadic Function)

无论是 C/C++ 还是 javascript/python,都支持变长参数函数。在 Go 里典型的变长参数就是 fmt.Printf 函数。那这种函数如何定义呢?

1. 变长参数函数定义和使用

变长参数函数定义如下:

func name(paramname ...type) return-list

即在参数名后面加上 ... 符号就行了。关于 ... 符号,在 Go 里之前已经出现过一次了,在数组那一篇,不知道你是否还记得。

例如你可以定义一个求和函数:

func sum(vals ...int) int {
    s := 0
    for _, val := range vals {
        s += val
    }
    return s
}

接下来你可以这样调用它:

fmt.Println(sum(1, 2, 3, 4)) // Output: 10

在 sum 函数内部,vals 的类型实际上是一个 []int 类型的 slice,但是它与 func sum(vals []int) int 是不同类型的函数。sum 函数的类型实际上是 func(...int) int.

当你调用 sum(1, 2, 3, 4) 的时候,实际上会隐式的创建一个大小为 4 的 int 类型数组,然后再获取该数组的切片传递给 sum 函数。

你还可以这样调用 sum 函数:

// 对于已经是 slice 的变量,你需要在变量后面加上 ...
a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(sum(a...)) // Output: 45

2. 其它疑惑

对于上面的 sum 函数你可能还是不太满意。因为 sum 函数要求接收的所有参数类型都是 int,然而fmt.Printf 却不一样,它可以接收任意类型的参数!这是怎么做到的?

实际上,如果你查阅 fmt.Printf 函数的声明,你会发现它是这样定义的:

func Printf(format string, a ...interface{}) (n int, err error)

只不过,变长参数的类型是 interface{},是的,这个类型前面你已经见过好多次了。当时我解释说,暂且理解为,如果参数是 interface{} 类型,就认为它可以接收任意类型的变量。

关于 interface 关键字,后面会很快接触到,所以咱们暂且先跳过它。

3. 总结

  • 掌握变长参数函数定义方式

思考:如果参数列表有多个参数,变长参数后面是否可以放在第一位?为什么?比如说下面这样行不行?

func sum(vals ...int, x int, y int) int

练习:写一个求最大值的变长参数版本的 max 函数。比如 max(4, 1, 9, 5) 会返回 9.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值