Variadic Functions in Go

Variadic Functions in Go

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

Variadic Functions in Go

Functions, in general, accept only a fixed number of arguments. A variadic function is a function that accepts a variable number of arguments.

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

Run in playground

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

Run in playground

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

Run in playground

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

Run in playground

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

Run in playground

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

Run in playground

Variadic Functions in Go
Scroll to top