Уроки модуля (2/5)
Срезы: идиоматическая структура
Срез — наиболее часто используемая структура данных в Go: динамическое представление.
над базовым массивом. Синтаксис: []T. В отличие от массивов, длина
не является частью типа, и вы можете расширить его с помощью append.
Анатомия среза
Внутренне срез представляет собой трехполевую структуру:
- указатель на первый элемент базового массива
- длина (
len): количество видимых элементов. - емкость (
cap): элементы доступны с начала представления. до конца базового массива
s := []int{10, 20, 30}
fmt.Println(len(s), cap(s)) // 3 3Создание
a := []int{1, 2, 3} // literal
b := make([]int, 3) // [0 0 0] len=3 cap=3
c := make([]int, 3, 10) // len=3 cap=10 (reserved)
var d []int // nil slice: len=0 cap=0, still usable with appendappend: всегда присваивать результат
append добавляет элементы и возвращает новый фрагмент (потенциально
выделение нового массива, если емкости недостаточно):
s := []int{1, 2, 3}
s = append(s, 4) // [1 2 3 4]
s = append(s, 5, 6, 7) // append multiple elements
s = append(s, altra...) // concatenate another slice (spread)Выражение фрагмента s[a:b]
Извлекает подфрагмент от a (включительно) до b (эксклюзивно):
s := []int{10, 20, 30, 40, 50}
sub := s[1:4] // [20 30 40]
inizio := s[:2] // [10 20]
fine := s[3:] // [40 50]
intera := s[:] // [10 20 30 40 50]Подсрезы совместно используют базовый массив с исходным срезом:
мутации через sub[i] = ... также видны в s.
Подводный камень: совместное использование массива
s := []int{1, 2, 3, 4}
sub := s[0:2]
sub[0] = 99
fmt.Println(s) // [99 2 3 4] — modified!Чтобы получить независимую копию, используйте copy или append:
out := make([]int, len(sub))
copy(out, sub)Попробуйте это
Создайте срез с [1, 2, 3] и используйте добавление, чтобы добавить 4.
Показать подсказку
ВСЕГДА присваивайте результат добавления обратно в `s`.
Решение доступно после 3 попыток
Используйте выражение среза для извлечения элементов от индекса 1 включительно до индекса 3 включительно (т. е. [20, 30]).
Показать подсказку
Синтаксис: `s[start:end]`, `start` включительно, `end` исключая.
Решение доступно после 3 попыток
Что из этого писать НЕПРАВИЛЬНО?
s := []int{1, 2, 3}
// (a) s = append(s, 4)
// (b) append(s, 4)Резюме
[]T: динамический просмотр массива; тройной (птр, лен, кап).make([]T, len, cap)для предварительного выделения;var s []Tдля полезного нулевого среза.s = append(s, ...): ВСЕГДА присваивайте результат.s[a:b]использует базовый массив:copy(...)для независимых копий.- Срез
nil= можно читать, ранжировать или добавлять; совершенно отличается от нулевой карты.