Passing arguments to ... parameters

December 26, 2023

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 ... parameters

If f is variadic with a final parameter p of type ....T, then within f the type of p is equivalent to type []T. If f is invoked with no actual arguments for p, the value passed to p is nil. 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 to T. 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 value nil 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


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .