Variadic Functions in Go
In this tutorial, we are going to discuss on Variadic Functions in Go language. A variadic function is a function that accepts zero, one, or more values as a single argument.

Functions in general accept only a fixed number of arguments. A variadic function is a function that accepts a variable number of arguments.
A function with a parameter that is preceded with a set of ellipses (...
) is considered a variadic function. The ellipsis means that the parameter provided can be zero, one, or more values. For the fmt.Println
package, it is stating that the parameter a
is variadic.
Variadic functions are not the common case, they can be used to make your code cleaner and more readable.
These functions are more common than they seem. The most common one is the Println
function from the fmt
package.
func Println(a ...interface{}) (n int, err error)
Letβs create a program that uses the fmt.Println
function and pass in zero, one, or more values:
package main
import "fmt"
func main() {
fmt.Println()
fmt.Println("Way")
fmt.Println("Way", "to")
fmt.Println("Way", "to", "easy")
fmt.Println("Way", "to", "easy", "learn")
}
Output
Way
Way to
Way to easy
Way to easy learn
Defining a Variadic Function
We can define a variadic function by using an ellipsis (...
) in front of the argument. Letβs create a program that greets people when their names are sent to the function:
Syntax
func f(elem ...Type)
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.
package main
import "fmt"
func main() {
sayHello()
sayHello("Ashok")
sayHello("Sai", "Rama", "Seetha")
}
func sayHello(names ...string) {
for _, n := range names {
fmt.Println("Hello ", n)
}
}
Output
Hello Ashok
Hello Sai
Hello Rama
Hello Seetha
We created a sayHello
function that takes only a single parameter called names
. The parameter is variadic, as we put an ellipsis (...
) before the data type: ...string
. This tells Go that the function can accept zero, one, or many arguments.
The sayHello
function receives the names
parameter as a slice
. Since the data type is a string
, the names
parameter can be treated just like a slice of strings ([]string
) inside the function body. We can create a loop with the range
operator and iterate through the slice of strings.
Notice that nothing printed for the first time we called sayHello
. This is because the variadic parameter was an empty slice
of string
. Since we are looping through the slice, there is nothing to iterate through, and fmt.Printf
is never called.
Variadic Argument Order
You can only have one variadic parameter in a function, and it must be the last parameter defined in the function. Defining parameters in a variadic function in any order other than the last parameter will result in a compilation error:
package main
import "fmt"
func main() {
sayHello("Hello")
sayHello("Ashok", "Hello")
sayHello("Sai", "Rama", "Seetha", "Hello")
}
func sayHello(names β¦string, message string) {
for _, name := range names {
fmt.Println(message, name)
}
}
Output
./prog.go:11:15: syntax error: cannot use ... with non-final parameter names
When defining any variadic function, only the last parameter can be variadic.
package main
import "fmt"
func main() {
sayHello("Hello")
sayHello("Hello", "Ashok")
sayHello("Hello", "Sai", "Rama", "Seetha")
}
func sayHello(message string, names β¦string) {
for _, name := range names {
fmt.Println(message, name)
}
}
Output
Hello Ashok
Hello Sai
Hello Rama
Hello Seetha
Exploding Arguments
So far, we have seen that we can pass zero, one, or more values to a variadic function. However, there will be occasions when we have a slice of values and we want to send them to a variadic function.
package main
import "fmt"
func main() {
names := []string{"Ashok", "Sai", "Rama", "Seetha"}
sayHello("Hello", names)
}
func sayHello(message string, names ...string) {
for _, name := range names {
fmt.Println(message, name)
}
}
Output
./prog.go:7:14: cannot use names (type []string) as type string in argument to sayHello
Even though the variadic function will convert the parameter of values ...string
to a slice of strings []string
, we canβt pass a slice of strings as the argument. This is because the compiler expects discrete arguments of strings.
To work around this, we can explode a slice by suffixing it with a set of ellipses (...
) and turning it into discrete arguments that will be passed to a variadic function.
package main
import "fmt"
func main() {
names := []string{"Ashok", "Sai", "Rama", "Seetha"}
sayHello("Hello", names...)
}
func sayHello(message string, names ...string) {
for _, name := range names {
fmt.Println(message, name)
}
}
Output
Hello Ashok
Hello Sai
Hello Rama
Hello Seetha
Itβs important to note that we can still pass a zero, one, or more arguments, as well as a slice that we explode. Here is the code passing all the variations that we have seen so far
package main
import "fmt"
func main() {
sayHello("Hello")
sayHello("Hello", "Ashok")
sayHello("Hello", "Sai", "Rama", "Seetha")
fmt.Println("---------------")
sayHello("Hello", []string{"Ashok", "Sai", "Rama", "Seetha"}β¦)
}
func sayHello(message string, names β¦string) {
for _, name := range names {
fmt.Println(message, name)
}
}
Output
Hello Ashok
Hello Sai
Hello Rama
Hello Seetha
---------------
Hello Ashok
Hello Sai
Hello Rama
Hello Seetha