Область действия сборщика мусора (Garbage Collector) в Go: стек или куча?

Ответ

Сборщик мусора (Garbage Collector, GC) в Go работает исключительно с кучей (heap).

Разберёмся почему:

  • Стек (Stack)

    • Память на стеке выделяется для локальных переменных функции (аргументы, переменные, объявленные внутри функции).
    • Время жизни этих переменных строго ограничено временем выполнения функции.
    • Память освобождается автоматически при выходе из функции (по принципу LIFO — Last In, First Out). Управление стеком очень быстрое и детерминированное, GC здесь не нужен.
  • Куча (Heap)

    • Память в куче выделяется для данных, время жизни которых не связано с конкретным вызовом функции. Это данные, которые должны "пережить" функцию, в которой были созданы.
    • В Go компилятор с помощью анализа побега (escape analysis) решает, где выделить переменную: на стеке или в куче. Если компилятор видит, что на переменную берётся указатель, который возвращается из функции, эта переменная "сбегает" в кучу.
    • Именно за объектами в куче и следит GC. Он периодически сканирует память, находит объекты, на которые больше нет ссылок (из стеков горутин или глобальных переменных), и освобождает занимаемое ими место.

Пример с анализом побега:

func createInt() *int {
    // Компилятор видит, что ссылка на 'x' возвращается наружу.
    // Поэтому 'x' будет выделена в куче, а не на стеке.
    x := 42 
    return &x
}

func main() {
    // ptr указывает на память в куче. 
    // Когда ptr выйдет из области видимости (или станет nil),
    // GC сможет освободить память, где хранилось значение 42.
    ptr := createInt() 
    fmt.Println(*ptr)
}