Где в Go выделяется память под переменные, объявленные внутри функции?

Ответ

В Go память для переменных, объявленных в функции, выделяется либо в стеке (stack), либо в куче (heap). Решение принимает компилятор на этапе компиляции в процессе, который называется анализ на утечку (escape analysis).

1. Выделение в стеке (Stack Allocation)

Это стандартное поведение для большинства локальных переменных. Стек — это быстрая, самоочищающаяся область памяти. Память выделяется при входе в функцию и автоматически освобождается при выходе из нее.

Пример:

func calculateSum() int {
    a := 5 // 'a' создается в стеке
    b := 10 // 'b' создается в стеке
    return a + b
} // Память под 'a' и 'b' освобождается здесь

2. Выделение в куче (Heap Allocation / "Escape")

Если компилятор определяет, что переменная должна "пережить" вызов функции (например, на нее остается ссылка вне функции), он перемещает ее в кучу. Память в куче управляется сборщиком мусора (Garbage Collector).

Причины "утечки" в кучу:

  • Возврат указателя на локальную переменную.
  • Захват переменной замыканием (closure), которое переживает функцию.
  • Сохранение ссылки на переменную в глобальной переменной или передача в другую горутину.

Пример:

func createUser(name string) *User {
    u := User{Name: name} // 'u' будет создана в куче
    return &u // т.к. мы возвращаем указатель на нее
}

Вывод: По умолчанию переменные создаются в стеке для максимальной производительности. Если переменная должна существовать после завершения функции, компилятор перемещает её в кучу.