← Назад к вопросам

Какой рассчитывается Capacity слайса?

2.0 Middle🔥 171 комментариев
#Другое#Основы Go

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Управление Capacity в слайсах Go

В Go Capacity (cap) слайса — это максимальное количество элементов, которое может вместить его внутренний массив (underlying array) без необходимости выделения новой памяти. Capacity рассчитывается и управляется автоматически runtime Go, но его механизм важно понимать для оптимизации производительности.

Как capacity рассчитывается при создании и росте слайса

Capacity слайса определяется в момент его создания и изменяется при операциях, требующих увеличения его размера.

1. Инициализация через make()

При создании слайса с помощью make() можно явно указать capacity:

// Создаём слайс с length=3 и capacity=5
s := make([]int, 3, 5)
fmt.Println(len(s)) // 3
fmt.Println(cap(s)) // 5

2. Инициализация среза от массива или другого слайса

При создании слайса через срез (slice) от существующего массива или слайса, capacity рассчитывается как количество элементов в исходном массиве от начального индекса до конца:

arr := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := arr[2:6] // slice включает элементы arr[2]..arr[5]
fmt.Println(len(slice)) // 4 (элементы 2,3,4,5)
fmt.Println(cap(slice)) // 8 (от arr[2] до arr[9] — 8 элементов)

// Для слайса, срезанного от другого слайса:
parent := []int{1, 2, 3, 4, 5}
child := parent[1:3]
fmt.Println(cap(child)) // 4 (от parent[1] до конца родителя)

Ключевой механизм: динамическое увеличение capacity при append()

Когда функция append() добавляет элементы в слайс и его текущая capacity недостаточна, происходит реаллокация (reallocation) — выделение нового массива большего размера. Алгоритм роста capacity не фиксирован в спецификации языка, но в текущей реализации runtime Go действует следующее правило:

Правила роста capacity:

  • При маленьких размерах (<1024 элементов): capacity увеличивается вдвое (double) при каждой реаллокации.
  • При больших размерах (>1024 элементов): capacity увеличивается примерно на 25% (quarter growth).

Пример динамического увеличения:

s := make([]int, 0, 2) // len=0, cap=2
fmt.Println("Initial cap:", cap(s))

s = append(s, 1, 2) // cap=2, len=2 — capacity ещё достаточна
fmt.Println("After first append, cap:", cap(s))

s = append(s, 3) // len=3 > cap=2 — требуется реаллокация
fmt.Println("After overflow append, cap:", cap(s)) // Новый cap будет 4 (удвоение)

// Добавим ещё элементы до превышения
s = append(s, 4, 5) // len=5 > cap=4 — ещё одна реаллокация
fmt.Println("After second overflow, cap:", cap(s)) // Новый cap будет 8

Оптимизация через управление capacity

Правильное управление capacity критично для производительности, поскольку реаллокации требуют:

  1. Выделения новой памяти
  2. Копирования всех существующих элементов
  3. Утилизации старого массива (если не используется)

Лучшие практики:

  • Предварительное выделение (Pre-allocation): Если известно ожидаемое количество элементов, создавайте слайс с достаточной capacity через make():
// Плохо: многократные реаллокации при добавлении 1000 элементов
var s []int
for i := 0; i < 1000; i++ {
    s = append(s, i)
}

// Хорошо: одна реаллокация (или вообще без нее)
s := make([]int, 0, 1000)
for i := 0; i < 1000; i++ {
    s = append(s, i)
}
  • Использование len и cap при срезании: Помните, что срез (slice) слайса сохраняет его исходную capacity, что может привести к неявному удержанию большого массива в памяти. Используйте полный срез (full slice expression) s[low:high:max] для ограничения capacity нового слайса:
bigSlice := make([]int, 10000)
smallSlice := bigSlice[0:10] // cap(smallSlice) = 10000 — всё ещё ссылается на большой массив!

// Ограничиваем capacity нового слайса
controlledSlice := bigSlice[0:10:10] // len=10, cap=10
fmt.Println(cap(controlledSlice)) // 10

Таким образом, capacity в Go — это не просто свойство слайса, а механизм управления памятью, который требует внимания разработчика для баланса между удобством использования и эффективностью кода.

Какой рассчитывается Capacity слайса? | PrepBro