Вопрос проверяет понимание модели памяти в Go и того, как горутины используют стек и кучу для своего выполнения.
В Go каждая горутина — это легковесный поток выполнения, который работает в адресном пространстве одного процесса. В отличие от потоков ОС, горутины не имеют фиксированного большого стека. Вместо этого каждая горутина получает свой собственный стек, который изначально очень мал (обычно 2-4 КБ) и может динамически расширяться и сжиматься по мере необходимости.
Стек горутины выделяется из кучи (heap) Go. Когда горутина создается, рантайм Go выделяет для нее начальный стек в куче. Если стек становится недостаточным, рантайм копирует его в новый, больший блок памяти в куче. Это позволяет эффективно использовать память, так как большинство горутин не требуют большого стека.
package main
import (
"fmt"
"runtime"
)
func main() {
// Показываем количество горутин
fmt.Println("Number of goroutines:", runtime.NumGoroutine())
// Создаем горутину
go func() {
fmt.Println("Hello from goroutine")
}()
// Даем время горутине выполниться
runtime.Gosched()
fmt.Println("Number of goroutines after creation:", runtime.NumGoroutine())
}В этом примере при вызове go func() рантайм выделяет новый стек для этой горутины в куче. После завершения функции стек освобождается.
Память для горутин хранится в куче Go, что позволяет эффективно управлять ресурсами и создавать тысячи горутин без значительного потребления памяти. Это делает Go идеальным для высоконагруженных приложений, таких как веб-серверы и сетевые сервисы.