Каналы и select
О чём этот блок
Каналы и select — это «нервная система» конкурентной Go-программы. Через них
горутины передают данные, сигналят об отмене и договариваются, кто что делает.
В реальных системах именно на этом фундаменте стоит всё остальное: отмена
запроса по таймауту, корректное завершение фоновых задач, приоритизация
трафика, защита от утечек горутин. Если вы научитесь думать о канале как о
точке синхронизации, а о его закрытии — как о широковещательном сигнале, то
половина задач про конкурентность перестанет быть магией.
Главная мысль блока: канал — это не просто очередь, а контракт о владении и
готовности. Отправитель и получатель встречаются в точке передачи; закрытие
канала «видно» всем читателям сразу; nil-канал блокирует навсегда и потому
служит выключателем для веток select.
Что вы научитесь делать
- Использовать закрытие канала как broadcast-сигнал отмены (
done-канал). - Строить композицию сигналов: «сработал любой из источников».
- Гарантированно завершать горутину-продьюсера, чтобы она не зависала на отправке в никем не читаемый канал.
- Управлять таймаутами и бездействием через
time.Timer/time.Afterвнутриselect. - Приоритизировать ветки
selectи при этом не допускать голодания (starvation). - Понимать разницу буферизированного и небуферизированного канала и её последствия для блокировок.
Карта задач
- 01 · Or-Channel — закрытие канала как broadcast; рекурсивная композиция
каналов через
select; завершение всех вспомогательных горутин без утечек. - 02 · Unbuffered канал и утечка горутины — классический goroutine leak:
продьюсер виснет на
ch <- i, когда потребитель ушёл. Лечитсяdone-каналом вselect. - 03 · Generator с таймаутом бездействия — самозавершающийся генератор:
сброс таймера после каждой успешной отправки, гонка двух веток
select(отправка vs таймаут), корректное закрытие канала. - 04 · Очередь с приоритетом на select — приоритизация
highнадlowчерез вложенныйselectсdefault; защита от голодания низкого приоритета; завершение по закрытию обоих каналов.
Связанные главы учебника
- Каналы — буфер и его отсутствие,
closeкак broadcast,nil-канал, направления каналов. - select — мультиплексирование,
default, отключение веток черезnil-каналы, таймауты. - Горутины и планировщик — почему зависшая на отправке горутина «стоит» памяти и как это связано с утечками.
// Идиома блока: select, который умеет и отправить, и сдаться по отмене.
select {
case out <- v: // удалось передать дальше
case <-done: // нас отменили — выходим, не виснем
return
}