Ответ
Горутина блокируется при вызове операции, которая требует ожидания (например, чтение/запись канала, системные вызовы, мьютексы). В этот момент планировщик Go (scheduler) вытесняет горутину и переключается на другую, пока блокировка не снимется.
Пример блокировки при чтении из канала:
ch := make(chan int)
go func() {
val := <-ch // Горутина блокируется здесь, пока в канал не запишут данные
fmt.Println(val)
}()
ch <- 42 // Разблокировка
Ключевые моменты:
- Блокировка не потребляет CPU
- Планировщик автоматически возобновит работу после разблокировки
- Для IO-операций runtime использует неблокирующие системные вызовы + event-loop