Расскажите о модели управления памятью в Go. Как и где выделяется память для переменных?

Ответ

В Go управление памятью автоматизировано с помощью сборщика мусора (GC). Память для переменных выделяется в двух основных областях: стеке (stack) и куче (heap).


  • Стек (Stack): Быстрая память, используемая для локальных переменных функции (аргументы, возвращаемые значения). Память на стеке выделяется и освобождается автоматически при входе в функцию и выходе из нее. Каждая горутина имеет свой собственный, изначально небольшой (около 2KB), динамически расширяемый стек.



  • Куча (Heap): Более медленная область памяти для данных, которые должны пережить вызов функции. Память в куче управляется сборщиком мусора.


Решение о том, где выделить память, принимает компилятор на основе анализа逃逸 (escape analysis). Если компилятор доказывает, что переменная не используется за пределами своей функции, она размещается на стеке. В противном случае она "сбегает" в кучу.

Пример "сбегающей" переменной (выделение в куче):

// x "сбегает", так как ссылка на неё возвращается из функции
func createPointer() *int {
    x := 42
    return &x // x будет выделена в куче
}

Пример переменной, остающейся в стеке:

// y не покидает пределы функции, остается на стеке
func calculate() int {
    y := 10
    return y * 2 // y будет выделена на стеке
}

Таким образом, Go-разработчику не нужно вручную управлять памятью, но понимание escape analysis помогает писать более производительный код.