Ответ
Горутина может быть убрана из потока (descheduled) в следующих случаях:
- Блокирующие операции - вызовы типа
time.Sleep(), канальные операции (<-chan), системные вызовы (I/O, мьютексы) - Вызов
runtime.Gosched()- явное освобождение потока для других горутин - Превышение кванта времени - примерно 10мс на горутину (зависит от версии Go)
- Работа сборщика мусора - GC может приостанавливать горутины
Пример блокировки по каналу:
ch := make(chan int)
go func() {
<-ch // горутина заблокируется здесь
fmt.Println("Received")
}()
Горутины управляются планировщиком Go (не ОС), что делает переключения легковесными.