Go Academy · Урок

Стек и куча, анализ выхода за пределы стека

Как Go определяет, где выделять память

Урок 1 из 413 шагов

«Стек и куча, анализ выхода за пределы стека» — бесплатный урок Go Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Выделение памяти в стеке

Локальные переменные, которые не выходят за пределы функции, размещаются в стеке горутины. Выделение памяти в стеке выполняется быстро (достаточно увеличить указатель), а сборка такой памяти не требует затрат (при возврате стековый кадр удаляется).

Выделение памяти в куче

Переменные, которые выходят в кучу, выделяются аллокатором Go и отслеживаются сборщиком мусора. Выделение памяти в куче выполняется медленнее и увеличивает нагрузку на сборщик мусора.

Что вызывает выход в кучу?

Распространённые причины выхода в кучу: получение адреса локальной переменной и её возврат, сохранение локальной переменной в интерфейсе или отправка по каналу. Анализ выхода в кучу выполняет компилятор.

func newUser() *User { // *User escapes to heap
    return &User{Name: "Alice"}
}

go build -gcflags=-m

Выведите решения анализа выхода в кучу:

go build -gcflags="-m" .
// main.go:10:15: &User literal escapes to heap
// main.go:5:14: s does not escape

Стеки горутин

Каждая горутина запускается с небольшим стеком (2 КиБ в Go 1.14 и более поздних версиях), который при необходимости динамически увеличивается. Стеки отделены от кучи и освобождаются после завершения горутины.

Как избегать выделения памяти

Передавайте небольшие структуры по значению, а не по указателю. Используйте массивы, размещённые в стеке, вместо срезов, если размер известен. Возвращайте значения, а не указатели, чтобы сохранять их в стеке.

Упаковка в интерфейс

Присваивание конкретного значения интерфейсу приводит к выходу значения в кучу (упаковке). Для часто выполняемых участков кода принимайте конкретные типы или используйте обобщения вместо интерфейсов.

sync.Pool

Повторно используйте объекты, выделенные в куче, с помощью sync.Pool, чтобы уменьшить нагрузку на сборщик мусора из-за частого выделения краткоживущих объектов (буферов, контекстов запросов).

var pool = sync.Pool{New: func() any { return make([]byte, 1024) }}
buf := pool.Get().([]byte)
defer pool.Put(buf[:0])

Профилирование выделений памяти

Используйте go test -benchmem и профилирование кучи с помощью -alloc_space, чтобы найти функции, выделяющие больше всего памяти.

Срез и массив

Небольшой массив [N]T может оставаться в стеке. Заголовок среза (24 байта) размещается в стеке, но его базовый массив может выйти в кучу. Предварительное выделение памяти с помощью make предотвращает повторное перераспределение.

Интернирование строк

Строковые литералы не размещаются в куче (они находятся в сегменте данных, доступном только для чтения). Преобразование []byte в string выделяет память. Кэшируйте часто используемые строки, чтобы избежать повторных преобразований.

Быстрая проверка

Из-за чего локальная переменная выходит из стека в кучу?

Итоги: стек и куча

Основные положения:

  • Стек: быстрое размещение, сборка мусора не требуется; куча: медленнее, отслеживается сборщиком мусора
  • go build -gcflags="-m" показывает решения анализа выхода в кучу
  • Упаковка в интерфейс, получение адреса локальной переменной и отправка по каналу вызывают выход в кучу
  • Используйте sync.Pool для часто выделяемых и удаляемых объектов
Можно начать бесплатно

Изучай Go с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
51
Уроки
203

Часто задаваемые вопросы

Урок «Стек и куча, анализ выхода за пределы стека» бесплатный?

Да — полный текст урока «Стек и куча, анализ выхода за пределы стека» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Стек и куча, анализ выхода за пределы стека»?

Как Go определяет, где выделять память Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Стек и куча, анализ выхода за пределы стека»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Стек и куча, анализ выхода за пределы стека
  2. Модель памяти Go и Happens-Before
  3. Внутреннее устройство сборщика мусора
  4. Сокращение выделений: sync.Pool и арены
← Назад к Go Academy