Слайсы (часть 2)¶
Теперь — про подводные камни. Слайс это не сам массив, а «окно» в массив. Несколько слайсов могут смотреть на одни и те же данные, и одно изменение случайно ломает другой слайс. Это самый частый источник багов у новичков.
Что должен понять¶
- Что слайс — это тройка (указатель, len, cap).
- Что такое shared backing array и как два слайса делят память.
- Как сделать независимую копию через
copy. - Что делает выражение
s[low:high:max](ограничение cap). - Как
appendможет создать новый массив, а может писать в чужой.
Shared backing array¶
arr := []int{1, 2, 3, 4, 5}
a := arr[1:4] // [2 3 4]
b := arr[2:5] // [3 4 5]
a[1] = 99 // меняем arr[2]
fmt.Println(arr) // [1 2 99 4 5]
fmt.Println(b) // [99 4 5] <-- b тоже изменился
a и b смотрят в один и тот же массив. Изменение через одно «окно»
видно через другое.
Slicing с тремя индексами s[low:high:max]¶
max ограничивает cap, чтобы будущий append не залез в чужую память:
arr := []int{1, 2, 3, 4, 5}
safe := arr[1:3:3] // len=2, cap=2
safe = append(safe, 99) // создаст новый массив
fmt.Println(arr) // [1 2 3 4 5] — не пострадал
Без третьего индекса append мог бы записать поверх arr[3].
copy — независимая копия¶
src := []int{1, 2, 3}
dst := make([]int, len(src))
n := copy(dst, src) // n = 3
dst[0] = 99
fmt.Println(src, dst) // [1 2 3] [99 2 3]
copy копирует min(len(dst), len(src)) элементов.
append: когда new array, когда нет¶
- Если
len < cap—appendпишет в существующий массив, ёмкость хватает. - Если
len == cap— Go аллоцирует новый массив (обычно ×2) и копирует.
s := make([]int, 0, 4)
s = append(s, 1, 2, 3, 4) // тот же массив
s = append(s, 5) // новый массив, cap вырос
Из-за этого функция, принимающая слайс, может или поменять оригинал,
или работать с копией — в зависимости от ёмкости. Всегда присваивай
результат append обратно.
Частые ошибки¶
- Сделали
b := a[2:4], поменялиb[0]и удивляются, чтоaизменился. - В цикле копируют через
b = a— это тот же слайс, а не копия. - Передают слайс в функцию, ждут что не изменится — а функция делает
s[0] = 0и оригинал ломается. - Используют
arr[1:3]в долгоживущей переменной, держа в памяти весь большой массив. Если нужен только кусок — копируй.
Критерии приёмки модуля¶
- Программа демонстрирует shared backing array на двух слайсах.
- Программа делает независимую копию через
copyи доказывает, что изменение копии не трогает оригинал. - Программа использует
s[low:high:max]хотя бы один раз. - Решение не выходит за границу слайса.
Дальше: Мапы.