Variadic Functions in Go
In this tutorial, we are going to discuss 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 by 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 in Go 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 an elem variable of the type []Type, a slice. Hence, all arguments passed to this function are stored in an 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 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
That’s all about the Variadic Functions in Go language. If you have any queries or feedback, please write us email at contact@waytoeasylearn.com. Enjoy learning, Enjoy Go language.!!