В Go канал — это средство передачи данных между горутинами с синхронизацией. Различают:
Использовать небуферизованные каналы удобно там, где критична синхронизация, и нужно гарантировать, что отправитель и получатель встретились в одном месте кода. Буферизованные подходят для передачи данных «с запасом» — для организации очередей, воркеров, асинхронных задач.
func main() { ch := make(chan int) // небуферизованный go func() { ch <- 42 // блокируется, пока нет приёмника }() fmt.Println(<-ch) bufch := make(chan int, 2) // буферизованный на 2 элемента bufch <- 1 // не блокируется bufch <- 2 // не блокируется // следующий send заблокируется, если не будет чтения }
Может ли буферизованный канал служить заменой очереди между десятками продюсеров и консюмеров без доп. синхронизации?
Часто отвечают — «да». На деле, только если не важна гарантия порядка и сообщения не теряются. При нескольких читателях/писателях возможны ситуации гонок и потери данных, поэтому контроль синхронизации всё равно нужен (worker pool, мьютексы, контексты для закрытия каналов).
История
В процессинге логов программисты использовали буферизованный канал длиной 1000 для передачи событий между парсером и аггрегатором. При остановке сервиса забыли закрыть канал, и часть событий "потерялась" — воркеры завершились до обработки всего буфера. Было исправлено явным закрытием каналов и блокировкой до полной выгрузки.
История
При попытке заменить mutex-очередь на буферизованный канал в распределённом сервисе не учли ситуации "зависших" отправителей: при полном буфере send-блокировка в итоге замедлила всю систему, привела к тайм-аутам, а интерфейс начал "лагать". После анализа вернули часть синхронизации обратно через condition variables.
История
В телеметрическом модуле использовался небуферизованный канал для лога ошибок между модулем и консюмером. Из-за случайной задержки обработки писалка блокировалась, и за минуту накопилась очередь из сотен тысяч данных в горутинах — возник "out of goroutines". Исправили, заменив небуферизованный канал на буферизованный и асинхронного воркера очистки очереди.