Ответ
В Go куча (heap) — это общая область памяти, доступная всем горутинам одновременно. Важно отметить, что мы говорим именно о горутинах, а не о потоках ОС, так как это ключевая абстракция в Go.
Основные принципы взаимодействия:
Общий доступ: Все горутины разделяют одну и ту же кучу для динамического выделения памяти. Это позволяет легко обмениваться данными между горутинами через указатели.
Управление сборщиком мусора (GC): Память в куче управляется автоматическим сборщиком мусора. Разработчику не нужно вручную освобождать память. GC отслеживает объекты, на которые больше нет ссылок, и освобождает их.
Синхронизация выделения памяти: Сам процесс выделения памяти в куче (
make
,new
) является потокобезопасной операцией. Go runtime гарантирует, что одновременные аллокации из разных горутин не приведут к повреждению данных."Побег в кучу" (Escape Analysis): Не все переменные, объявленные в функции, остаются на её стеке. Если компилятор определяет, что на переменную будут ссылаться после завершения функции (например, при возврате указателя), он размещает её в куче. Этот процесс называется escape analysis.
Пример "побега" переменной в кучу:
// Эта функция возвращает указатель на локальную переменную.
func createUser(name string) *User {
u := User{Name: name} // 'u' будет размещена в куче, а не на стеке,
return &u // так как ссылка на неё "убегает" из функции.
}
Влияние на производительность:
Частые аллокации в куче создают нагрузку на сборщик мусора, что может приводить к кратковременным остановкам приложения (stop-the-world pauses). Для оптимизации производительности стараются минимизировать ненужные аллокации в куче.
Узнать, какие переменные "убегают" в кучу, можно с помощью флага компилятора:
go build -gcflags="-m" ./...