Как в Go происходит выделение памяти в стеке и куче, и в чем ключевые различия?

Ответ

В Go, как и в других компилируемых языках, память для переменных выделяется либо в стеке (stack), либо в куче (heap). Компилятор Go самостоятельно решает, где разместить переменную, с помощью механизма под названием анализ побега (escape analysis).

Стек (Stack)

  • Что это: Область памяти для локальных переменных функции (аргументы, переменные, объявленные внутри функции).
  • Принцип работы: Память выделяется при входе в функцию и автоматически освобождается при выходе из нее. Это очень быстрая операция (простое смещение указателя стека).
  • Ограничения: Размер стека ограничен, и переменные не могут "пережить" вызов функции, в которой они были созданы.

Куча (Heap)

  • Что это: Область памяти для данных, время жизни которых не связано с конкретной функцией. Эти данные могут использоваться в разных частях программы.
  • Принцип работы: Выделение памяти в куче — более медленная операция. Освобождением этой памяти занимается сборщик мусора (Garbage Collector, GC), который периодически ищет объекты в куче, на которые больше нет ссылок, и освобождает их.

Анализ побега (Escape Analysis)

Это процесс, в ходе которого компилятор определяет, "сбегает" ли переменная из своей функции. Если переменная не сбегает, она размещается в стеке. Если сбегает — в куче.

Переменная "сбегает" в кучу, если:

  1. На нее возвращается указатель из функции.
  2. Она используется в замыкании, которое переживает функцию.
  3. Ее размер слишком велик для стека.
  4. Она передается в функцию через interface{}.

Пример:

// x будет выделен в стеке, так как он не "сбегает" из функции.
func stackAlloc() int {
    x := 42
    return x
}

// x будет выделен в куче, так как указатель на него
// возвращается и переживает вызов функции.
func heapAlloc() *int {
    x := 42
    return &x // &x "сбегает" в кучу
}
ХарактеристикаСтек (Stack)Куча (Heap)
СкоростьОчень высокаяМедленнее
Время жизниОграничено вызовом функцииУправляется сборщиком мусора (GC)
УправлениеАвтоматическое (компилятор)Автоматическое (GC)
РазмерНебольшой и фиксированныйБольшой и динамический