Модульні уроки (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)Спробуйте
Створіть фрагмент s за допомогою [1, 2, 3] і використовуйте append, щоб додати 4.
Показати підказку
ЗАВЖДИ призначайте результат додавання назад до `s`.
Рішення доступне після 3 спроб
Використовуйте вираз зрізу, щоб витягти елементи з індексу 1 включно до 3 винятково (тобто [20, 30]).
Показати підказку
Синтаксис: `s[початок:кінець]`, `початок` включно, `кінець` винятково.
Рішення доступне після 3 спроб
Що з цього НЕПРАВИЛЬНО написати?
s := []int{1, 2, 3}
// (a) s = append(s, 4)
// (b) append(s, 4)Підведення підсумків
[]T: динамічний перегляд масиву; потрійний (ptr, len, cap).make([]T, len, cap)для попереднього розподілу;var s []Tдля корисного нульового фрагмента.s = append(s, ...): ЗАВЖДИ призначати результат.s[a:b]спільно використовує базовий масив:copy(...)для незалежних копій.- Зріз
nil= OK для читання/діапазону/додавання; дуже відрізняється від нульової карти.