Использование распространения при инициализации массива в Go - PullRequest
0 голосов
/ 24 сентября 2019

У меня есть повторяющийся список значений, которые я хочу использовать при инициализации нескольких таких массивов:

package main

import (
    "fmt"
)

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

Этот код выше дает следующую ошибку:

./prog.go:9:20: синтаксическая ошибка: неожиданно ..., ожидается запятая или}

Я хотел использовать оператор распространения ..., но это пока невозможноинициализация массива.

Я что-то здесь упускаю или распространение не разрешено?

1 Ответ

2 голосов
/ 24 сентября 2019

Вы можете использовать ... со срезом только при передаче его в функцию с переменным числом аргументов.См. Spec: Передача аргументов в ... параметры .

Так, например, вы можете использовать его при передаче в append():

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

Какие выходы (попробуйте на Go Playground ):

[2 1 2 3 3]

В качестве альтернативы вышеприведенное можно записать в одну строку:

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

Примечаниечто это может быть компактно, это не обязательно эффективно, так как может создавать и копировать несколько резервных массивов под капотом.

Чтобы обеспечить одно выделение, вы можете использовать make() с предоставленной емкостью, например:

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

Попробуйте это на Go Playground .

Еще одно решение - использовать copy(), если у вас есть предварительно выделенный фрагмент (либос make() или с использованием индексов в литерале композиции):

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

Попробуйте это на Go Playground .Недостатком здесь является то, что индекс (4: 3) должен быть постоянным и не может быть чем-то вроде 1 + len(i).Если вы хотите предварительно выделить фрагмент (например, make([]int, 2+len(i))), вы не можете комбинировать это с составным литералом для элементов списка.

...