Ответ
Память для горутин выделяется и управляется средой выполнения Go (runtime), а не напрямую операционной системой. Основные моменты:
Стек горутины: Каждая горутина получает собственный стек. Изначально он очень мал (обычно 2 КБ), что позволяет создавать сотни тысяч горутин без больших затрат памяти.
- Этот стек выделяется в куче (heap), а не в стеке системного потока.
- Стек может динамически расти и сжиматься по мере необходимости. Если горутине требуется больше места, среда выполнения выделяет новый, больший сегмент стека и копирует в него старые данные.
Размещение переменных (Анализ ускользания): Компилятор Go выполняет анализ ускользания (escape analysis), чтобы решить, где разместить переменную — на стеке горутины или в общей куче.
- На стеке: Локальные переменные, чьё время жизни не превышает время выполнения функции, размещаются на стеке. Это очень эффективно, так как память очищается автоматически при выходе из функции.
- В куче: Если компилятор определяет, что на переменную будут ссылаться после завершения функции (например, её адрес возвращается или передаётся в другую горутину), переменная «ускользает» в кучу. Память в куче управляется сборщиком мусора (GC).
func main() {
go func() {
// 'a' будет размещена на стеке этой горутины
a := 42
// 'b' будет размещена в куче, так как new() всегда выделяет память в куче.
b := new(int)
*b = 100
}()
}