Ответ
Планировщик Go (scheduler) автоматически вытесняет горутины, выполняющие блокирующие операции (как сетевые запросы), передавая управление другим горутинам.
Когда горутина делает блокирующий syscall (например, HTTP-запрос):
- Связывает текущий поток (M) с сетевым дескриптором
- Планировщик отсоединяет M от процессора (P)
- Создает/берет новый M из пула для выполнения других горутин
- Когда syscall завершается, M пытается вернуться к своему P или становится в очередь
Пример:
go func() {
resp, err := http.Get("https://example.com") // Блокирующий вызов
// Планировщик переключится здесь
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
}()
Это позволяет эффективно использовать ресурсы CPU, пока горутина ожидает ответа сети.