Соедините два ломтика в Go

Я пытаюсь объединить срез [1, 2] и срез [3, 4]. Как я могу сделать это в Go?

Я пробовал:

append([]int{1,2}, []int{3,4})

но получил:

cannot use []int literal (type []int) as type int in append

Однако документация, кажется, указывает, что это возможно, что мне не хватает?

slice = append(slice, anotherSlice...)

Ответ 1

Добавьте точки после второго фрагмента:

//---------------------------vvv
append([]int{1,2}, []int{3,4}...)

Это подобно любой другой вариационной функции.

func foo(is ...int) {
    for i := 0; i < len(is); i++ {
        fmt.Println(is[i])
    }
}

func main() {
    foo([]int{9,8,7,6,5}...)
}

Ответ 2

Добавление и копирование фрагментов

Вариантная функция append добавляет ноль или более значений x в sтипа s, который должен быть типом среза, и возвращает результат срез, также типа s. Значения x передаются параметру type ...T, где T - тип элемента s и соответствующий применяются правила передачи параметров. В качестве специального случая добавление также принимает первый аргумент, присваиваемый типу []byte со вторым аргументом string, за которым следует .... Эта форма добавляет байты строка.

append(s S, x ...T) S  // T is the element type of S

s0 := []int{0, 0}
s1 := append(s0, 2)        // append a single element     s1 == []int{0, 0, 2}
s2 := append(s1, 3, 5, 7)  // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
s3 := append(s2, s0...)    // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}

Передача аргументов... параметрам

Если f является переменным с конечным типом параметра ...T, то в пределах function аргумент эквивалентен параметру типа []T. В каждый вызов f, аргумент, переданный окончательному параметру, является новым срез типа []T, чьи последующие элементы являются фактическими аргументами, которые все должны быть назначены типу T. Длина среза равна поэтому количество аргументов, связанных с конечным параметром, и может отличаются для каждого сайта вызова.

Ответ на ваш вопрос - пример s3 := append(s2, s0...) в Go Language Language Specification. Например,

s := append([]int{1, 2}, []int{3, 4}...)

Ответ 3

Ничего, кроме других ответов, но я нашел краткое объяснение в документах более понятным, чем примеры в них:

func append

func append(slice []Type, elems ...Type) []Type Добавление встроенного функция добавляет элементы в конец фрагмента. Если этого достаточно пропускная способность, место назначения перераспределяется для размещения новых элементов. Если это не так, будет выделен новый базовый массив. присоединять возвращает обновленный фрагмент. Поэтому необходимо сохранить результат добавления, часто в переменной, содержащей сам срез:

slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)

В качестве специального случая законно добавлять строку в байтовый срез, например:

slice = append([]byte("hello "), "world"...)

Ответ 4

Я думаю, что важно отметить и знать, что если срез назначения (фрагмент, который вы добавляете) имеет достаточную емкость, добавление произойдет "на месте", путем переназначения адресата (reslicing, чтобы увеличить его длину).

Это означает, что если цель создается путем нарезки большего массива или среза, который имеет дополнительные элементы за пределами длины результирующего фрагмента, они могут быть перезаписаны.

Чтобы продемонстрировать это, см. этот пример:

a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)

x, y := a[:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))

x = append(x, y...)
fmt.Printf("x: %v\n", x)

fmt.Printf("a: %v\n", a)

Вывод (попробуйте на Go Playground):

a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 10
x: [1 2 3 4]
a: [1 2 3 4 0 0 0 0 0 0]

Мы создали массив поддержки a с длиной 10. Затем мы создаем срез назначения x, разрезая этот массив a, срез y создается с использованием составного литерала []int{3, 4}. Теперь, когда мы добавляем y в x, результатом является ожидаемый [1 2 3 4], но что может быть удивительно, так это то, что массив поддержки a также изменился, поскольку емкость x равна 10, что является достаточным для добавления y к нему, поэтому x будет resliced, который также будет использовать тот же массив поддержки a, а append() будет копировать элементы y туда.

Если вы хотите этого избежать, вы можете использовать выражение full slice, которое имеет форму

a[low : high : max]

который создает срез, а также управляет результирующей емкостью среза, устанавливая его на max - low.

См. измененный пример (единственное отличие состоит в том, что мы создаем x следующим образом: x = a[:2:2]:

a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)

x, y := a[:2:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))

x = append(x, y...)
fmt.Printf("x: %v\n", x)

fmt.Printf("a: %v\n", a)

Выход (попробуйте на Go Playground)

a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 2
x: [1 2 3 4]
a: [1 2 0 0 0 0 0 0 0 0]

Как вы можете видеть, мы получаем тот же результат x, но массив поддержки a не изменился, поскольку емкость x была "only" 2 (благодаря полному фрагментам выражения a[:2:2]). Итак, чтобы добавить append, выделяется новый массив поддержки, который может хранить элементы как x, так и y, который отличается от a.