Search code examples
govariadic-functionsvariadic

Variadic Variable Expansion in fmt.Println


package main
import "fmt"
func main(){
        a := []int{1,2,3}
        fmt.Println(a...)
}

Running this gives the following error

./program.go:5: cannot use a (type []int) as type []interface {} in argument to fmt.Println

From godoc fmt Println

func Println(a ...interface{}) (n int, err error)

Println accepts any value because it is an empty interface.

What's confusing to me is that

fmt.Println(a...) is same as fmt.Println(a[0],a[1],a[2])

and yet one works but the other doesn't.

What am I missing here?


Solution

  • []int is not the same as []interface{}, so if you have an []int, you can't pass that to fmt.Println() as the value for the variadic slice. You may pass it as-is, but that's gonna be an []interface{} slice with a single value being the []int slice.

    fmt.Println(a...) is not the same as fmt.Println(a[0],a[1],a[2]).

    fmt.Println(a[0], a[1], a[2]) is equivalent to

    fmt.Println([]interface{}{a[0], a[1], a[2]}...)
    

    which is equivalent to

    fmt.Println([]interface{}{
        interface{}(a[0]),
        interface{}(a[1]),
        interface{}(a[2]),
    }...)
    

    So when you pass a[0], a[1] and a[2], implicit interface{} values will be created, which will be implicitly wrapped in a slice.

    If you would want to pass elements of a to a function that expects a variadic parameter of []interface{}, you have to "manually" create that slice beforehand, e.g.:

    b := make([]interface{}, len(a))
    for i, v := range a {
        b[i] = v
    }
    fmt.Println(b...)
    

    Try these examples on the Go Playground.

    Also see related question: Unpacking slice of slices