Ответ
В Go, как и в других компилируемых языках, память для переменных выделяется либо в стеке (stack), либо в куче (heap). Компилятор Go самостоятельно решает, где разместить переменную, с помощью механизма под названием анализ побега (escape analysis).
Стек (Stack)
- Что это: Область памяти для локальных переменных функции (аргументы, переменные, объявленные внутри функции).
- Принцип работы: Память выделяется при входе в функцию и автоматически освобождается при выходе из нее. Это очень быстрая операция (простое смещение указателя стека).
- Ограничения: Размер стека ограничен, и переменные не могут "пережить" вызов функции, в которой они были созданы.
Куча (Heap)
- Что это: Область памяти для данных, время жизни которых не связано с конкретной функцией. Эти данные могут использоваться в разных частях программы.
- Принцип работы: Выделение памяти в куче — более медленная операция. Освобождением этой памяти занимается сборщик мусора (Garbage Collector, GC), который периодически ищет объекты в куче, на которые больше нет ссылок, и освобождает их.
Анализ побега (Escape Analysis)
Это процесс, в ходе которого компилятор определяет, "сбегает" ли переменная из своей функции. Если переменная не сбегает, она размещается в стеке. Если сбегает — в куче.
Переменная "сбегает" в кучу, если:
- На нее возвращается указатель из функции.
- Она используется в замыкании, которое переживает функцию.
- Ее размер слишком велик для стека.
- Она передается в функцию через
interface{}
.
Пример:
// x будет выделен в стеке, так как он не "сбегает" из функции.
func stackAlloc() int {
x := 42
return x
}
// x будет выделен в куче, так как указатель на него
// возвращается и переживает вызов функции.
func heapAlloc() *int {
x := 42
return &x // &x "сбегает" в кучу
}
Характеристика | Стек (Stack) | Куча (Heap) |
---|---|---|
Скорость | Очень высокая | Медленнее |
Время жизни | Ограничено вызовом функции | Управляется сборщиком мусора (GC) |
Управление | Автоматическое (компилятор) | Автоматическое (GC) |
Размер | Небольшой и фиксированный | Большой и динамический |