В чем различия между стеком и хипом в Go
Что проверяют
Знаете ли вы, что в Go место размещения переменной выбирает компилятор, а не программист. Следом почти всегда спрашивают про escape analysis и просят показать, как узнать, куда попала конкретная переменная.
Как отвечать
Начните с устройства:
- стек: у каждой горутины свой, стартует с 2 КБ и растёт по необходимости. Когда места не хватает, рантайм выделяет стек вдвое больше, копирует туда старый и корректирует указатели, которые на него смотрят. Предел по умолчанию 1 ГБ на 64-битных системах, при превышении программа падает с
fatal error: stack overflow; - хип: общая память процесса, её освобождает сборщик мусора. GC в Go конкурентный, трёхцветный mark-and-sweep, без поколений и без перемещения объектов. Частоту сборок задаёт
GOGC(по умолчанию 100), мягкий потолок памяти задаётGOMEMLIMIT; - escape analysis: компилятор проверяет, может ли значение пережить свою функцию. Не может, значит стек, иначе хип. Типичные причины «побега»: возврат указателя на локальную переменную, сохранение в интерфейс, захват замыканием, которое живёт дольше функции, слайс с размером, неизвестным при компиляции или слишком большим;
- как проверить:
go build -gcflags=-mпечатает решения компилятора вродеmoved to heap: xиescapes to heap, а число аллокаций видно в бенчмарке с флагом-benchmemили черезb.ReportAllocs().
Главное про производительность: выделение на стеке почти бесплатное и не нагружает GC, а каждая аллокация в хипе добавляет работу сборщику. Поэтому в горячем коде считают аллокации, переиспользуют буферы через sync.Pool и не передают мелкие структуры по указателю без нужды.
Где спотыкаются
Говорят, что new(T) и &T{} всегда выделяют память в хипе, а обычное объявление всегда на стеке. Ни синтаксис, ни make этого не определяют, решает только анализ.
Переносят опыт C и утверждают, что возвращать указатель на локальную переменную опасно. В Go это корректный код, переменная просто уедет в хип.
Объясняют разницу скоростью чтения. Дорого не обращение к хипу, а само выделение и последующая сборка мусора.