AquilaX
AquilaX

Reputation: 1278

Using spread when initializing array in Go

I have a repeating list of values which I want to re-use when initializing several arrays like that:

package main

import (
    "fmt"
)

func main() {
    var i = []int{1, 2, 3}
    var a = []int{2, i..., 3}
    fmt.Println(a)
}

This code above gives the following error:

./prog.go:9:20: syntax error: unexpected ..., expecting comma or }

I wanted to use the spread ... operator but this does not seem to be possible while initializing an array.

Am I missing something here or spreading is not allowed?

Upvotes: 6

Views: 7543

Answers (1)

icza
icza

Reputation: 418435

You can only use ... with a slice when passing it to a variadic function. See Spec: Passing arguments to ... parameters.

So for example you could use it when passing it to append():

var i = []int{1, 2, 3}
a := append([]int{2}, i...)
a = append(a, 3)
fmt.Println(a)

Which outputs (try it on the Go Playground):

[2 1 2 3 3]

Alternatively the above can be written in one line:

a := append(append([]int{2}, i...), 3)

Do note that this may be compact, it's not necessarily efficient as it may create and copy multiple backing arrays under the hood.

To ensure a single allocation, you could use make() with capacity provided, for example:

a := make([]int, 0, 2+len(i))
a = append(a, 2)
a = append(a, i...)
a = append(a, 3)

Try this one on the Go Playground.

Yet another solution is to use copy() if you have the slice preallocated (either with make() or using indices in the compositle literal):

a := []int{2, 4: 3}
copy(a[1:], i)

Try this one on the Go Playground. The disadvantage here is that the index (4: 3) must be constant and can't be something like 1 + len(i). If you'd want to preallocate the slice (e.g. make([]int, 2+len(i))), you can't combine that with a composite literal to list elements.

Upvotes: 12

Related Questions