Что происходит, когда канал в Go заполняется и пишущая горутина блокируется
Что проверяют
Понимаете ли вы, что блокировка это не занятый поток, и знаете ли, чем оборачивается отсутствие читателя.
Как отвечать
Когда буфер канала заполнен, операция отправки блокируется. Важно, что происходит дальше на уровне рантайма: планировщик снимает горутину с потока операционной системы и переводит её в состояние ожидания, помещая в очередь отправителей этого канала. Поток при этом свободен и берёт другую горутину. Никакого активного ожидания нет, стоимость блокировки близка к нулю, поэтому блокирующих операций в Go не боятся.
Разбудят её так: когда читатель заберёт значение, рантайм возьмёт первого ожидающего отправителя из очереди, скопирует его значение и пометит горутину готовой к выполнению. При этом значение может передаваться напрямую, минуя буфер.
У небуферизованного канала буфера нет вовсе, поэтому отправка блокируется всегда до момента, когда появится готовый получатель. Это точка встречи двух горутин.
Главная опасность, о которой и спрашивают: если читателя не будет никогда, горутина заблокирована навсегда. Это утечка горутин. Рантайм сообщит об этом только в случае, когда заблокированы абсолютно все горутины программы. В работающем сервисе таких горутин может накапливаться тысячами, и видно это по росту их числа в pprof, а не по ошибке.
Как не допускать:
selectсdefaultдля неблокирующей отправки, когда терять значение допустимо;selectс<-ctx.Done()или таймаутом, чтобы отправитель мог уйти;- осознанный размер буфера: он задаёт, насколько производитель может обгонять потребителя, и его переполнение это сигнал, что потребитель не справляется;
- ясная ответственность за закрытие: закрывает канал только отправитель, и только один.
Стоит добавить про закрытый канал: чтение из него возвращает нулевое значение с признаком false, а отправка вызывает панику.
Где спотыкаются
Думают, что заблокированная горутина занимает поток.
Не закладывают выход по контексту и получают утечку горутин.
Закрывают канал со стороны читателя.
Ждут, что рантайм всегда сообщит о зависшей горутине.