Горутина в Go состоит из нескольких ключевых компонентов:
g
структура в runtime) - содержит метаданные и контекст выполнения// Упрощенная структура горутины из runtime/runtime2.go
type g struct {
stack stack // Описание стека (нижняя и верхняя границы)
stackguard0 uintptr // Проверка переполнения стека
sched gobuf // Контекст выполнения (регистры, PC, SP)
m *m // Привязанный поток ОС
atomicstatus uint32 // Текущее состояние горутины
}
Горутины используют сегментированные (split) стеки:
+---------------+
| Новый стек | (4KB)
+---------------+
| Копия данных |
+---------------+
| |
+---------------+
| Старый стек | (2KB) -> будет освобожден
+---------------+
Можно изменить через runtime/debug.SetMaxStack
Пример измерения:
func measureGoroutineMem() {
var before, after runtime.MemStats
runtime.ReadMemStats(&before)
var wg sync.WaitGroup
wg.Add(10000)
for i := 0; i < 10000; i++ {
go func() {
defer wg.Done()
runtime.Gosched()
}()
}
wg.Wait()
runtime.ReadMemStats(&after)
fmt.Printf("Memory per goroutine: %.2f KB\n",
float64(after.HeapAlloc-before.HeapAlloc)/10000/1024)
}
Сжатие стека:
Работа с большими стеками:
runtime.morestack
Параметр | Горутина | Поток ОС |
---|---|---|
Начальный размер | 2KB | 1-8MB |
Максимальный размер | 1GB | Не ограничен |
Аллокация | Динамическая | Фиксированная |
Стоимость создания | 300ns |
1-10µs |
runtime.GOMAXPROCS
runtime.NumGoroutine()
для отслеживания количестваПример безопасного шаблона:
func workerPool(tasks <-chan Task, results chan<- Result, workers int) {
var wg sync.WaitGroup
wg.Add(workers)
for i := 0; i < workers; i++ {
go func() {
defer wg.Done()
for task := range tasks {
results <- process(task)
}
}()
}
go func() {
wg.Wait()
close(results)
}()
}
горутины в Go используют инновационную модель динамических стеков, позволяющую эффективно использовать память. Начальный размер стека всего 2KB делает их исключительно легковесными, а механизм сегментированных стеков обеспечивает гибкость при росте потребностей. Понимание этих механизмов помогает писать высокопроизводительные concurrent-приложения без риска исчерпания памяти.