Модуль
1map2Массивы3Слайсы← вы здесь4Структуры
Урок 2~12 минут

Слайсы

Слайс — гибкая обёртка над массивом

Слайс не хранит данные сам — он ссылается на backing array. Под капотом это три поля:

┌─────────┬─────┬─────┐
│  ptr    │ len │ cap │
└─────────┴─────┴─────┘
  • ptr — указатель на первый элемент в backing array
  • len — сколько элементов видно через слайс
  • cap — сколько элементов доступно до конца backing array

Создание слайса

go
// Литерал — создаёт backing array сразу
s := []int{1, 2, 3, 4, 5}
 
// make — задаём len и cap явно
s2 := make([]int, 3)     // len=3, cap=3
s3 := make([]int, 3, 10) // len=3, cap=10
 
// nil-слайс — нулевое значение, len=0, cap=0
var s4 []int
fmt.Println(s4 == nil) // true
fmt.Println(len(s4))   // 0 — безопасно использовать

append

append добавляет элементы в конец слайса:

go
s := []int{1, 2, 3}
s = append(s, 4)         // [1 2 3 4]
s = append(s, 5, 6, 7)   // [1 2 3 4 5 6 7]
s = append(s, []int{8, 9}...) // развернуть слайс

Если len == cap, append выделяет новый backing array (обычно в 2× больше) и копирует данные:

go
s := make([]int, 3, 3)
fmt.Printf("ptr=%p cap=%d\n", s, cap(s)) // ptr=X cap=3
 
s = append(s, 99)
fmt.Printf("ptr=%p cap=%d\n", s, cap(s)) // ptr=Y cap=6 — новый массив!

Поэтому всегда пиши s = append(s, ...) — результат может быть новым слайсом.


Подслайсы

go
s := []int{0, 1, 2, 3, 4, 5}
 
a := s[1:4]  // [1 2 3], len=3, cap=5
b := s[:3]   // [0 1 2]
c := s[3:]   // [3 4 5]

Подслайс делит backing array с оригиналом:

go
a[0] = 99
fmt.Println(s) // [0 99 2 3 4 5] — оригинал изменился!

copy

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

go
src := []int{1, 2, 3, 4, 5}
dst := make([]int, len(src))
copy(dst, src)
 
dst[0] = 99
fmt.Println(src) // [1 2 3 4 5] — не изменился

copy возвращает количество скопированных элементов — минимум из len(dst) и len(src).


Удаление элемента

В Go нет встроенного delete для слайса. Классический паттерн:

go
s := []int{1, 2, 3, 4, 5}
i := 2 // удаляем элемент с индексом 2
 
s = append(s[:i], s[i+1:]...)
fmt.Println(s) // [1 2 4 5]

Осторожно: это изменяет backing array. Если где-то есть другой слайс, ссылающийся на тот же массив — он увидит изменения.


Двумерные слайсы

go
// Матрица 3x3
matrix := make([][]int, 3)
for i := range matrix {
    matrix[i] = make([]int, 3)
}
matrix[1][1] = 5

Ёмкость и производительность

Если знаешь финальный размер — передай cap в make:

go
// Плохо: много реаллокаций
result := []int{}
for i := 0; i < 10000; i++ {
    result = append(result, i*i)
}
 
// Хорошо: один раз выделяем нужную память
result := make([]int, 0, 10000)
for i := 0; i < 10000; i++ {
    result = append(result, i*i)
}

Разница в производительности может быть в 5–10 раз на больших слайсах.

append может создать новый backing array. После append всегда присваивай результат обратно: s = append(s, x)
Слайсы в Go— интерактивная визуализация
Backing array (8 элементов)
10
[0]
20
[1]
30
[2]
40
[3]
50
[4]
60
[5]
70
[6]
80
[7]
в слайсе (len) доступно (cap)● ptr
Заголовок слайса (24 байта на 64-бит)
ptr0x1000→ arr[0]
len5элементов
cap8до конца arr
len: 5
arr := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
s := arr[0:5] // len=5, cap=8
// Заголовок слайса (slice header):
// ptr → &arr[0] (0x1000)
// len = 5
// cap = 8
🎯
Миссия 1 из 4
Из чего состоит слайс внутри?