Я пытаюсь совместить ломтик [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...)
go
append
slice
variadic-functions
Кевин Берк
источник
источник
append()
функция с переменным числом, и...
позволяет передавать несколько аргументов функции с переменным срезом.foo()
приведенном выше примереis
параметр содержит копию исходного среза, то есть копию легковесной ссылки на тот же базовый массив, len и cap. Еслиfoo
функция изменяет член, изменение будет видно на оригинале. Вот демо . Таким образом, единственными реальными издержками будет то, что он создает новый фрагмент, если у вас его еще нет, например:foo(1, 2, 3, 4, 5)
который создаст новый фрагмент, которыйis
будет содержать....
существующий срез, он просто пропускает этот срез. Когда вы передаете отдельные аргументы, он собирает их в новый фрагмент и передает его. Я не из первых рук знания точной механики, но я предполагаю , что это:foo(1, 2, 3, 4, 5)
и это:func foo(is ...int) {
только де-сахар к этому:foo([]int{1, 2, 3, 4, 5})
и это:func foo(is []int) {
.Пример ответа на ваш вопрос приведен
s3 := append(s2, s0...)
в спецификации языка программирования Go . Например,источник
a[low : high : max]
), которое также определяет максимальную емкость . Например, срезa[0:2:4]
будет иметь емкость,4
и он не может быть повторно включен для включения элементов, выходящих за рамки этого, даже если после этого массив резервных копий имеет тысячу элементов.Ничего против других ответов, но я нашел краткое объяснение в документах более понятным, чем примеры в них:
источник
Я думаю, что важно указать и знать, что, если срез назначения (срез, к которому вы добавляете) имеет достаточную емкость, добавление произойдет «на месте», путем изменения назначения (с целью увеличения его длины, чтобы быть в состоянии разместить дополняемые элементы).
Это означает, что если место назначения было создано путем нарезки большего массива или среза, у которого есть дополнительные элементы, превышающие длину полученного среза, они могут быть перезаписаны.
Чтобы продемонстрировать, посмотрите этот пример:
Вывод (попробуйте на Go Playground ):
Мы создали «резервный» массив
a
с длиной10
. Затем мы создаемx
срез назначения, разрезая этотa
массив,y
срез создается с использованием составного литерала[]int{3, 4}
. Теперь , когда мы добавляемy
кx
, результат является ожидаемым[1 2 3 4]
, но то , что может быть удивительного в том , что массив поддержкаa
также изменился, потому что способностьx
IS ,10
которая достаточна для добавленияy
к нему, такx
как resliced , который также будет использовать тот жеa
массив подкладочный иappend()
скопирую элементыy
туда.Если вы хотите избежать этого, вы можете использовать полное выражение слайса, которое имеет вид
который создает срез, а также управляет емкостью результирующего среза, установив его в
max - low
.Смотрите модифицированный пример (единственное отличие в том, что мы создаем
x
такx = a[:2:2]
:Выход (попробуйте на Go Playground )
Как вы можете видеть, мы получаем тот же
x
результат, но резервный массивa
не изменился, потому что емкостьx
была «единственной»2
(благодаря полному выражению слайсаa[:2:2]
). Таким образом, чтобы выполнить добавление, выделяется новый резервный массив, который может хранить элементы обоихx
иy
отличных отa
.источник
Я хотел бы подчеркнуть ответ @icza и немного упростить его, так как это очень важная концепция. Я предполагаю, что читатель знаком с кусочками .
Это правильный ответ на вопрос. НО, если вам нужно использовать фрагменты 'a' и 'c' позже в коде в другом контексте, это не безопасный способ объединения фрагментов.
Чтобы объяснить, давайте прочитаем выражение не с точки зрения срезов, а с точки зрения базовых массивов:
append () не обязательно создает новый массив! Это может привести к неожиданным результатам. Смотрите пример Go Playground .
Всегда используйте функцию make (), если хотите убедиться, что для массива выделен новый массив. Например, вот несколько уродливых, но достаточно эффективных вариантов для этой задачи.
источник
функция append () и оператор распространения
Два среза могут быть объединены с использованием
append
метода в стандартной библиотеке Голанга. Что похоже на работуvariadic
функции. Так что нам нужно использовать...
источник
append([]int{1,2}, []int{3,4}...)
будет работать. Передача аргументов...
параметры.Если
f
переменная с конечным параметромp
типа...T
, то внутриf
типаp
эквивалентна типу[]T
.Если
f
вызывается без фактических аргументовp
, передается значениеp
isnil
.В противном случае переданное значение представляет собой новый фрагмент типа
[]T
с новым базовым массивом, чьи последовательные элементы являются фактическими аргументами, которым все должны быть назначеныT
. Следовательно, длина и емкость фрагмента - это количество связанных аргументов, которыеp
могут отличаться для каждого сайта вызовов.Учитывая функцию и вызовы
источник