Зачем нужны каналы в Go и в чем разница между буферизованными и небуферизованными каналами
Что проверяют
Понимаете ли вы, что канал это не просто очередь, а средство синхронизации, и знаете ли, когда буфер меняет поведение программы.
Как отвечать
Канал передаёт значения между горутинами и одновременно синхронизирует их. Отсюда лозунг: разделяйте память через общение, а не общайтесь через общую память.
Небуферизованный (make(chan int)) это точка встречи: отправка блокируется, пока другая горутина не начнёт чтение, и наоборот. Передача происходит одновременно, поэтому такой канал даёт ещё и гарантию порядка: после успешной отправки вы знаете, что получатель уже её принял.
Буферизованный (make(chan int, 10)): отправка блокируется только когда буфер полон, чтение только когда он пуст. Это развязка по скорости: производитель может убежать вперёд на размер буфера.
jobs := make(chan Job, 100) // очередь задач
results := make(chan Result) // синхронная передача результатаКогда что выбирать: небуферизованный, когда важна синхронизация и подтверждение приёма; буферизованный, когда нужно сгладить неравномерность нагрузки или ограничить число одновременных операций (семафор из канала фиксированной ёмкости).
Где спотыкаются
Думают, что буфер спасает от дедлока. Он лишь отодвигает блокировку: когда буфер заполнится, отправитель встанет так же.
Отправляют в небуферизованный канал в той же горутине, где потом собираются читать, и получают мгновенный дедлок.
Закрывают канал со стороны получателя: закрывать должен отправитель, запись в закрытый канал это паника.
Забывают, что чтение из закрытого канала сразу возвращает нулевое значение, и путают «канал закрыт» с «данных пока нет».