Перейти к основному содержимому
Модуль 4 · Урок 2 из 517/50 в курсе~15 min
Уроки модуля (2/5)

Срезы: идиоматическая структура

Срез — наиболее часто используемая структура данных в Go: динамическое представление. над базовым массивом. Синтаксис: []T. В отличие от массивов, длина не является частью типа, и вы можете расширить его с помощью append.

Анатомия среза

Внутренне срез представляет собой трехполевую структуру:

  • указатель на первый элемент базового массива
  • длина (len): количество видимых элементов.
  • емкость (cap): элементы доступны с начала представления. до конца базового массива
Go
s := []int{10, 20, 30}
fmt.Println(len(s), cap(s)) // 3 3

Создание

Go
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 append

append: всегда присваивать результат

append добавляет элементы и возвращает новый фрагмент (потенциально выделение нового массива, если емкости недостаточно):

Go
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 (эксклюзивно):

Go
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.

Подводный камень: совместное использование массива

Go
s := []int{1, 2, 3, 4}
sub := s[0:2]
sub[0] = 99
fmt.Println(s)             // [99 2 3 4] — modified!

Чтобы получить независимую копию, используйте copy или append:

Go
out := make([]int, len(sub))
copy(out, sub)

Попробуйте это

Упражнение#go.m4.l2.e1
Попыток: 0Загрузка…

Создайте срез с [1, 2, 3] и используйте добавление, чтобы добавить 4.

Загрузка редактора…
Показать подсказку

ВСЕГДА присваивайте результат добавления обратно в `s`.

Решение доступно после 3 попыток

Упражнение#go.m4.l2.e2
Попыток: 0Загрузка…

Используйте выражение среза для извлечения элементов от индекса 1 включительно до индекса 3 включительно (т. е. [20, 30]).

Загрузка редактора…
Показать подсказку

Синтаксис: `s[start:end]`, `start` включительно, `end` исключая.

Решение доступно после 3 попыток

Quiz#go.m4.l2.e3
Готово

Что из этого писать НЕПРАВИЛЬНО?

Go
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 = можно читать, ранжировать или добавлять; совершенно отличается от нулевой карты.