воскресенье, 10 мая 2020 г.

Как добавить что-либо (элемент, срез или строку) к срезу в Golang

С помощью встроенной функции append вы можете использовать срез в качестве динамического массива. Функция добавляет любое количество элементов в конец среза:

  • если емкости достаточно, базовый массив используется повторно;
  • если нет, выделяется новый базовый массив и данные копируются.

append возвращает обновленный срез, поэтому вам нужно сохранить результат добавления, часто в переменной, содержащей сам срез:

a := []int{1, 2}
a = append(a, 3, 4) // a == [1 2 3 4]

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

a := []int{}
a = append(a, 3, 4) // a == [3 4]

Предупреждение. Вот пример того, что может произойти, если вы забудете, что append может повторно использовать базовый массив:

a := []byte("ba")

a1 := append(a, 'd')
a2 := append(a, 'g')

fmt.Println(string(a1)) // bag
fmt.Println(string(a2)) // bag

Если есть место для большего количества элементов, append повторно использует базовый массив. Давайте взглянем:

a := []byte("ba")
fmt.Println(len(a), cap(a)) // 2 32
// длина среза - 2, но емкость - 32

Это означает, что срезы a, a1 и a2 будут ссылаться на один и тот же базовый массив в нашем примере.

Чтобы избежать этого, нам нужно использовать два отдельных байтовых массива.

const prefix = "ba"

a1 := append([]byte(prefix), 'd')
a2 := append([]byte(prefix), 'g')

fmt.Println(string(a1)) // bad
fmt.Println(string(a2)) // bag

Но бывает так что данная проблема не всегда сразу видна. В некоторых реализациях Go []byte("ba") выделяет только два байта, а затем код работает: первая строка "bad", а вторая "bag".

К сожалению, код по-прежнему неверен, хотя кажется, что он работает. Программа может вести себя иначе, когда вы запускаете ее в другой среде.

Добавить один срез в другой

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

a := []int{1, 2}
b := []int{11, 22}
a = append(a, b...) // a == [1 2 11 22]

... распаковывает b. Без точек код будет пытаться добавить срез целиком, что недопустимо.

Результат не зависит от того, перекрываются ли аргументы:

a := []int{1, 2}
a = append(a, a...) // a == [1 2 1 2]

Добавить строку к байтовому срезу

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

slice := append([]byte("Hello "), "world!"...)

Производительность

Добавление одного элемента занимает постоянное амортизированное время.


Читайте также:


Комментариев нет:

Отправить комментарий