Variadic Functions
Some functions should accept any number of arguments — fmt.Println takes one,
five, or none. In Go you write such a function with a variadic parameter,
marked by ... before its type.
Declaring a variadic parameter
Put ... in front of the final parameter's type. The caller can then pass zero,
one, or many values for it:
package main
import "fmt"
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
func main() {
fmt.Println(sum(1, 2, 3)) // 6
fmt.Println(sum()) // 0
fmt.Println(sum(10)) // 10
}
Only the last parameter can be variadic, and there can be only one.
Inside, it's just a slice
That ... is mostly caller-side sugar. Inside the function, nums has type
[]int — an ordinary slice. That's why the range loop above works with no
special syntax: you already know how to iterate a slice. When the caller passes
no arguments, nums is an empty (nil) slice, and the loop simply runs zero
times.
Spreading a slice with ...
Often you already have a slice and want to feed it to a variadic function. You
can't pass the slice directly — the types don't match. Instead, spread it by
writing ... after the slice at the call site:
package main
import "fmt"
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
func main() {
xs := []int{4, 8, 6}
fmt.Println(sum(xs...)) // 18
}
sum(xs...) unpacks xs into individual arguments. Note the symmetry: ...
in a declaration packs arguments into a slice; ... at a call unpacks a
slice into arguments.
One rule: don't mix a spread with extras
When you spread a slice, that spread must be the whole argument list for the variadic parameter — you can't tack on extra values:
sum(xs...) // ok
sum(1, 2, xs...) // compile error: too many arguments
If you need the extras, append them to the slice first, then spread the result.
You've been using them already
Variadic functions are everywhere in the standard library. fmt.Println(a, b, c) is variadic. So is the built-in append(slice, x, y, z) — and it accepts a
spread too: append(dst, src...) copies one slice onto the end of another. Once
you recognize the ..., you'll spot it constantly.
Practice
1. Variadic Max
BeginnerImplement
max, a variadic function that returns the largest of all the integers passed to it:func max(first int, rest ...int) intThe required
firstparameter guarantees there's always at least one value, so an empty call is impossible and the function always has an answer.For example:
max(3) // 3 max(1, 5, 2) // 5 max(-1, -9, -3) // -1It should also work with a spread slice:
nums := []int{4, 8, 6} max(nums[0], nums[1:]...) // 8Start your answer at
first, then loop overrest(which is an[]int), keeping the largest value seen.package main import "fmt" // max returns the largest of first and any values in rest. func max(first int, rest ...int) int { // TODO: implement return 0 } func main() { fmt.Println(max(1, 5, 2)) }Sign in to write and run your solution in the browser.
Sign in for hints and the solution.