Материал проходит вычитку — возможны неточности.
Урок 4 из 118

Срезы и aliasing

В предпросмотре импорта Миша взял кусок списка и дописал туда пробную запись. Наутро клиентский список показал чужое имя на месте своего — пробная запись заехала на хвост. Разбирались с Аней до вечера.

Главная мысль

срез s[low:high] создаёт новый заголовок на тот же массив, поэтому append к срезу может записать в хвост исходного слайса; [low:high:max] ограничивает ёмкость.

Срез делит массив

Go

Индексы полуоткрытые: low включается, high — нет. Ёмкость среза считается от low до конца подлежащего массива, поэтому у window длина 3, а ёмкость 4 — за элементом 40 в исходном массиве лежит ещё 50.

Append задевает исходник

window = append(window, 60)
fmt.Println(ids) // [10 20 30 40 60] — append перезаписал хвост исходного массива

append дописал 60 в ячейку, где раньше лежал 50. Для ids это выглядит как порча данных. Такое aliasing — самый частый источник багов со слайсами: два слайса делят массив, и один «незаметно» меняет данные другого.

Ограничить ёмкость

Третий индекс, full slice expression, фиксирует cap как max-low:

ids = []int{10, 20, 30, 40, 50} // сбрасываем ids после примера 2: примеры независимы

window := ids[1:4:4]
fmt.Println(cap(window)) // 3 — ёмкость равна длине
window = append(window, 60) // места нет, append выделит новый массив
fmt.Println(ids)         // [10 20 30 40 50] — исходник не тронут

Если нужно отрезать кусок так, чтобы дальнейший append гарантированно не трогал исходник, указывай max равным high. Это не полная изоляция: существующие элементы срез и исходник по-прежнему делят — запись window[0] = 99 изменит ids. Третий индекс ограничивает только будущий append.

В следующем уроке

Вы узнаете:

  • почему отрицательные индексы и low > high запрещены
  • как считаются len/cap у срезов s[:n], s[n:], s[:]
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Предпросмотр импорта берёт срез списка файлов: a := []int{10, 20, 30, 40, 50}; s := a[2:4]. Чему равны len(s) и cap(s)?

Вопрос 2 из 3

s := a[:n:n] ограничивает ёмкость. Верно ли, что после этого append к результату гарантированно не тронет исходник?

Вопрос 3 из 3

Полный срез a[1:4:4] защищает существующие элементы от изменений?

Итоги

Срез — новое окно на старый массив. append пишет в доступный хвост, поэтому чужие данные можно «портить»; [low:high:max] отсекает хвост, но не отменяет общность существующих элементов.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки