If you’ve been a reader for a while, you may recall back in April when I first talked about variadic functions. Now we’re ready to dig in a bit further to the details of how these mysterious creatures work.
First we’ll see how they work “from the inside”. That is, from the perspective of someone writing a variadic function.
Passing arguments to
...
parametersIf
f
is variadic with a final parameterp
of type ....T
, then withinf
the type ofp
is equivalent to type[]T
. Iff
is invoked with no actual arguments forp
, the value passed top
isnil
. Otherwise, the value passed is a new slice of type[]T
with a new underlying array whose successive elements are the actual arguments, which all must be assignable toT
. The length and capacity of the slice is therefore the number of arguments bound to p and may differ for each call site.Given the function and calls
func Greeting(prefix string, who ...string) Greeting("nobody") Greeting("hello:", "Joe", "Anna", "Eileen")
within
Greeting
, who will have the valuenil
in the first call, and[]string{"Joe", "Anna", "Eileen"}
in the second.
So in other words, from the perspective of the function author, these can be considered functionally equivalent, with identical implementations:
func Greeting(prefix string, who ...string) {
fmt.Printf("%s %s\n", prefix, strings.Join(who, ", "))
}
func Greeting(prefix string, who []string) {
fmt.Printf("%s %s\n", prefix, strings.Join(who, ", "))
}
Whether who
is a variadic argument, or an explicit []string
, the type of the argument is the same.
The only difference between these two is that the explicit []string
type may receive a non-nil, but empty value, whereas the variadic version cannot—it will always receive nil
, or a slice with at least one value.
func Greeting(prefix string, who ...string) {
if who == nil {
/* ... what to do when we're greeting nobody? ... */
} else if len(who) == 0 {
/* ... Cannot happen for a variadic input ... */
} else {
fmt.Printf("%s %s\n", prefix, strings.Join(who, ", "))
}
}
Quotes from The Go Programming Language Specification Version of August 2, 2023