Каналы

Тема дорожной карты · Golang

Каналы в Go — типизированные проводники, позволяющие goroutines обмениваться данными путём отправки и получения значений, воплощая девиз Go: «не общайтесь через разделяемую память — разделяйте память через общение». Канал создаётся с помощью make(chan T) для небуферизованного или make(chan T, n) для буферизованного варианта; оператор <- используется как для отправки (ch <- v), так и для получения (v := <-ch). Небуферизованные каналы обеспечивают гарантии синхронизации — отправка блокируется до появления получателя, — тогда как буферизованные каналы разделяют отправителя и получателя в пределах ёмкости буфера. Оператор select позволяет goroutine ожидать нескольких операций с каналами одновременно, обеспечивая мощные паттерны fan-in и таймаутов через context.WithTimeout. Закрытие канала с помощью close(ch) сигнализирует всем получателям об окончании передачи, а цикл range по закрытому каналу опустошает его корректно, делая каналы незаменимыми для конвейеров, пулов воркеров и сигналов отмены в конкурентных Go-программах.

Как это работает

Каналы построен на goroutines (лёгкие green threads, мультиплексируемые на OS-потоки Go-runtime) и channels (типизированные каналы для сообщений между goroutines). go funcName() запускает goroutine; ch <- value шлёт; value := <-ch принимает. select ждёт на нескольких каналах; context.Context несёт cancellation + дедлайны через дерево вызовов. sync.Mutex, sync.WaitGroup, sync.Once, атомарные примитивы, errgroup для группировки goroutines.

Когда применять

Goroutines используйте свободно — дёшевы (~2-4KB stack начально, растёт по нужде). Всегда имейте способ остановить goroutine (cancellation context.Context, close канала, deadline) — утёкшие goroutines = тихий рост памяти. Context первым аргументом — в любую функцию с I/O. sync.Mutex — для shared state, когда channels неудобны. errgroup — для "fan out, wait, первая ошибка пробрасывается".

Типичные ошибки

Ловушки Каналы: утечки goroutines (goroutine ждёт навеки на канале, в который никто не пишет); data race на shared map без mutex (race detector ловит: go test -race); deadlock (go test -race НЕ ловит deadlock — осторожно); не пробрасывают context.Context, и cancellation не доходит до глубокого вызова.

Связанные понятия

Полезные ресурсы