Ответ
Модель памяти в Go разделена на две основные области: стек (stack) и куча (heap). Управление памятью автоматизировано с помощью сборщика мусора (Garbage Collector, GC).
1. Стек (Stack)
- Назначение: Быстрая память для хранения локальных переменных, аргументов функций и возвращаемых значений. Память выделяется и освобождается автоматически при входе в функцию и выходе из неё.
- Особенности:
- У каждой горутины есть свой собственный, независимый стек.
- Начальный размер стека мал (~2 КБ), но он может динамически расти и сжиматься по мере необходимости.
- Доступ к стековой памяти очень быстрый (LIFO - Last-In, First-Out).
2. Куча (Heap)
- Назначение: Область памяти для хранения данных, которые должны "пережить" вызов функции, или данных, размер которых неизвестен на этапе компиляции. Сюда попадают все значения, которые "ускользают" (escape) из своего локального скоупа.
- Особенности:
- Память в куче управляется сборщиком мусора. Он отслеживает, какие объекты всё ещё используются, и освобождает память от неиспользуемых.
- Выделение памяти в куче медленнее, чем в стеке.
Анализ ускользания (Escape Analysis)
Это процесс, в ходе которого компилятор Go определяет, где выделить память для переменной — в стеке или в куче. Если компилятор доказывает, что переменная не будет использоваться после завершения функции, она размещается в стеке. В противном случае она "ускользает" в кучу.
// x "ускользает" в кучу, так как на неё остаётся ссылка
// за пределами функции.
func createInt() *int {
x := 42
return &x
}
Сборщик мусора (GC)
Go использует конкурентный (concurrent) сборщик мусора, основанный на алгоритме трёхцветной маркировки (tricolor mark-and-sweep). Он работает параллельно с основной программой, минимизируя паузы (stop-the-world pauses) до долей миллисекунды.
new()
и make()
new(T)
: Выделяет память для значения типаT
, инициализирует его нулевым значением и возвращает указатель*T
. Память всегда выделяется в куче.make(T, ...)
: Используется только для slices, maps и channels. Инициализирует внутренние структуры этих типов и возвращает готовое к использованию значение типаT
(не указатель). Память также выделяется в куче.