Стек и куча, анализ выхода за пределы стека
Как Go определяет, где выделять память
«Стек и куча, анализ выхода за пределы стека» — бесплатный урок 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 — локальная установка не требуется.
Все уроки этого курса
- Стек и куча, анализ выхода за пределы стека
- Модель памяти Go и Happens-Before
- Внутреннее устройство сборщика мусора
- Сокращение выделений: sync.Pool и арены