Variadic functions in Go

A variadic function accepts an infinite number of arguments and all these arguments are stored in a parameter of slice type.

Uday Hiwarale
Oct 14, 2018 · 4 min read

What is a variadic function?

As we have seen in a functions lesson, a function is a piece of code dedicated to do a particular job. A function takes one or many arguments and may return one or many values. Variadic functions are also functions but they can take an infinite or variable number of arguments. Sounds stupid but we have seen this in slices lesson when append function accepted a variable number of arguments.

func f(elem ...Type)

A typical syntax of a variadic function looks like above. ... operator called as pack operator instructs go to store all arguments of type Type in elem parameter. With this syntax, go creates elem variable of the type []Type which is a slice. Hence, all arguments passed to this function is stored in a elem slice.

Let’s take an example of append function.

append([]Type, args, arg2, argsN)

append function expects the first argument to be a slice of type Type, while there can be a variable number of arguments after that. If we have a slice s2 that we want to append to a slice s1, how that will work?

As from append function syntax, we can’t pass another slice as an argument, it has to be one or many arguments of type Type. Hence, instead, we will use the unpack operator ... to unpack slice into the series of arguments (which is acceptable by append function).

append(s1, s2...)

... signifies both pack and unpack operator but if three dots are in the tail position, it will unpack a slice.

Here s1 and s2 are two slices of the same type. Usually, we know function parameters and how many arguments a function can accept. Then how append function knows how many parameters has passed to it?

If you look at the signature append function,

func append(slice []Type, elems ...Type) []Type

You will see elems ...Type which means pack all incoming arguments into elems slice after the first argument.

One important thing to notice is that only the last argument of a function is allowed to be variadic.

So the first argument to append function will be a slice because it demands a slice but later arguments will be packed into one argument elems. I hope that makes it clear and now let’s look at creating your own variadic function.

☛ How to create a variadic function?

As discussed earlier, variadic function nothing but a function that accepts a variable number of arguments. To make a function accept a variable number of arguments, we need to use pack operator ...Type.

unpack operator ends with ... like slice... while pack operator starts with ... like ...Type.

Let’s write getMultiples function whose first argument is factor of type int which is a factor of multiplication and later variable arguments (hence variadic arguments) of type int are packed into the slice args.

In this function, we are creating an empty slice using make function with length equal to the length of args which is a slice. Using for range, we are multiplying factor with elements of args and saving them in multiples. Later, we return the slice multiples.

func getMultiples(factor int, args ...int) []int {
multiples := make([]int, len(args))
for index, val := range args {
multiples[index] = val * factor
}
return multiples
}

This is as simple as it can get. We can implement this function inside main function like

func main() {
s := []int{10, 20, 30}
mult1 := getMultiples(2, s...)
mult2 := getMultiples(3, 1, 2, 3, 4)
fmt.Println(mult1)
fmt.Println(mult2)
}
https://play.golang.org/p/BgU6H9orhrn

What will happen if in above example, you pass slice s directly to getMultiples function as second argument. Obviously, compiler will complain cannot use s (type []int) as type int in argument to getMultiples because slice is type of []int and getMultiples expects parameter(s) of int.

☛ How slice is passed to a variadic function?

A slice is a reference to an array, what happens when you pass a slice to a variadic function using unpack operator. Does go creates a new slice args or keeps the same slice s. Since, we don’t have any tool to compare, args == s, we need to mutate args slice itself to check if the original slice s mutated.

https://play.golang.org/p/fbNgVGu6JZO

In the above program, we have modified getMultiples variadic function slightly and instead of creating a new slice, we assigned multiplication values to args itself replacing incoming elements with multiplied elements.

From the above result, we can see values of slice s changed. This means, go in case of slice when passed to a variadic function using unpack operator, will use underneath array to build new slice. So, be careful.


RunGo

A place to find introductory Go Programming Language tutorials and learning resources. Like my other tutorials on Web Development, Run Go publication features important Go articles with deep dive into core of the language with examples and sample code.

Uday Hiwarale

Written by

IIT • Software Developer • India | Follow: github.com/thatisuday | Ask: thatisuday@gmail.com | World iza better place coz some still write on Medium for free :)

RunGo

RunGo

A place to find introductory Go Programming Language tutorials and learning resources. Like my other tutorials on Web Development, Run Go publication features important Go articles with deep dive into core of the language with examples and sample code.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade