Go 语言中的 variadic 函数允许接收一个类型可变数量的参数,得益于 ... 语法。例如:
func sum(nums ...int) int { total := 0 for _, num := range nums { total += num } return total }
可以使用任意数量的参数来调用此函数:
result := sum(1, 2, 3, 4) // 10
或者使用 ... 语法传递切片:
numbers := []int{1,2,3} result := sum(numbers...) // 6
细节:
[]T)。这意味着可以传入已准备好的切片。... 传递切片,函数会期望一个普通的参数类型 []T 而不是 variadic。以下代码的结果是多少,为什么?
func printInts(nums ...int) { fmt.Printf("%#v ", nums) } ints := []int{1, 2, 3} printInts(ints)
许多人错误地认为这段代码会编译成功,但实际上会引发编译错误:
错误: 不能不使用 ... 将切片传递给 variadic 参数。
正确:
printInts(ints...) // OK
故事
在一个大型项目中,日志记录函数被描述为 func Log(msgs ...string)。在传递已准备好的字符串切片时,直接调用 Log(strings),导致日志输出不正确或运行时 panic。原因是缺少 ...,因此函数将其视为一个类型为 []string 的参数,而不是单独的字符串。
故事
在一个工具函数中,需要处理参数,其中有一个切片,并希望在内部向其添加更多元素。原以为 ... 会创建切片的副本,而不是传递引用——但在函数内部修改切片,这意外影响了调用方,特别是当原切片是可重用的缓冲区时。
故事
开发人员使用 variadic 参数实现了聚合函数,但同事错误使用了通过类型转换的调用语法:sum(interface{}([]int)),这导致运行时隐性错误,而正确的做法是明确使用 sum(slice...)。对细节的不了解导致在大规模重构中出现难以察觉的 bug。