Passing arguments to
...
parameters…
If the final argument is assignable to a slice type
[]T
and is followed by...
, it is passed unchanged as the value for a...T
parameter. In this case no new slice is created.Given the slice
s
and calls := []string{"James", "Jasmine"} Greeting("goodbye:", s...)
within
Greeting
,who
will have the same value ass
with the same underlying array.
This leads to a few gotchas that I’ll spend today talking about.
The first, and probably most annoying, is that you cannot mix the s...
syntax with other arguments. In other words, the following is invalid:
kids := []string{"James", "Jasmine"}
Greeting("goodbye", "Mom", "Dad", kids...)
You can either provide individual arguments or a slice, not both. This leads to the rather cumbersome, but functional, alternative:
Greeting("goodbye", append([]string{"Mom", "Dad"}, kids...)...)
The second gotcha can bite you when working with slices of interfaces, particularly empty interfaces, though in principle it could happen with others. The gotcha is that it can be easy to forget the ...
suffix, and end up doing something you don’t intend. Let’s first examine a simple example involving fmt.Println
, then I’ll discuss what’s going on:
kids := []any{"James", "Jasmine"}
fmt.Println(kids...) // Prints: James Jasmine
fmt.Println(kids) // Prints: [James Jasmine]
If the reason for the difference in outputs above is not apparent, let me explain. In the first example, we pass a variadic argument, kids...
, which passes the kids
slice along to the called function, as the variadic argument.
In the second example, we’re passing the slice as a single argument, which in effect gets turned into []any{kids}
in the called function.
I’ve made this type of mistake more than once when working with the slog package, which has a number of functions that take a variadic ...any
argument. So beware!
Quotes from The Go Programming Language Specification Version of August 2, 2023