В Golang, куча (heap) — это область памяти, где размещаются динамически выделенные объекты. Управление этой памятью осуществляется автоматически сборщиком мусора.
Ключевые аспекты:
Динамическое выделение: Объекты небольшого размера и короткого времени жизни, где компилятор не может доказать, что их время жизни ограничено пределами функции или стека, или которые выделяются с помощью new или взятия адреса (&), обычно размещаются в куче.
Сборщик мусора (GC): Go использует concurrent, триколорный, Mark-and-Sweep сборщик мусора. Он работает одновременно с выполнением программы, минимизируя паузы.
Mark (Пометка): GC обходит достижимые объекты из корневых указателей (локальные переменные на стеках, глобальные переменные) и помечает их как "живые".
Sweep (Зачистка): GC проходит по всей доступной куче и освобождает память, занятую объектами, которые не были помечены как "живые".
Concurrent: GC работает в отдельных горутинах, уменьшая задержки в работе основной программы.
Escape Analysis: Компилятор Golang проводит анализ (escape analysis), чтобы определить, куда указывает переменная или значение — на стек или на кучу. Если переменная или структурное поле может быть доступно после возврата из текущей горутины, оно, скорее всего, будет выделено в куче. В противном случае, оно может быть выделено на стеке.// Пример escape analysis.
// Этот объект, скорее всего, будет выделен в куче,
// так как возвращается указатель.
func createPoint() *Point {
p := Point{X: 1, Y: 2}
return &p // Указатель "убегает" из функции
}
// Этот объект, скорее всего, будет выделен на стеке,
// так как он не доступен после завершения функции.
func processValue() {
val := 10
println(val)
}
type Point struct {
X, Y int
}
Разделение на арены (Arenas): Куча в Go может быть разделена на несколько арены, что помогает сборщику мусора работать более эффективно, особенно на многопроцессорных системах.
Использование mmap: Golang использует системный вызов mmap (Memory Map) для выделения больших блоков виртуальной памяти для кучи.
Непрерывность: В отличие от некоторых языков, Go не гарантирует физическую непрерывность объектов в куче. Память может быть фрагментирована.
Отсутствие ручного управления памятью: Разработчику не нужно явно выделять или освобождать память в куче. GC делает это автоматически.
Стек и куча в Golang выполняют разные роли: