Ответ
Не совсем. Для каждой новой горутины действительно выделяется своя уникальная структура g
, которая хранит её состояние (стек, счётчик команд и т.д.). Однако Go runtime активно оптимизирует этот процесс, используя пул (pool) уже созданных структур g
.
Как это работает:
- Когда горутина завершает свою работу, её структура
g
не уничтожается сразу, а помещается в специальный список свободных структур. - При запуске новой горутины (
go myFunc()
) runtime сначала пытается взять готовую структуруg
из этого пула. - Если пул пуст, только тогда будет выделена память под новую структуру
g
.
Этот механизм называется переиспользованием (pooling) и позволяет значительно снизить нагрузку на сборщик мусора и уменьшить накладные расходы на создание и уничтожение горутин, делая их запуск очень "дешевой" операцией.
Пример
func main() {
// Запускаем 1000 горутин
for i := 0; i < 1000; i++ {
go func(n int) {
// какая-то работа
}(i)
}
// Runtime будет активно переиспользовать структуры `g`
// для этих горутин, а не создавать все 1000 с нуля.
}
Вывод: Хотя каждая горутина логически является новой и имеет свою структуру g
, физически эта структура может быть не создана с нуля, а взята из пула для переиспользования.