Ответ
Каналы в Go — это типизированные конвейеры, которые обеспечивают безопасный обмен данными между горутинами, являясь одним из центральных элементов конкурентной модели Go.
Ключевые особенности:
-
Типы каналов: Буферизованные и небуферизованные
- Небуферизованные (
ch := make(chan int)
): Операции записи и чтения блокируются до тех пор, пока на другом конце канала не появится парная операция (чтение или запись). Это обеспечивает точку синхронизации (рандеву) между горутинами. - Буферизованные (
ch := make(chan int, 5)
): Позволяют отправлять данные без блокировки, пока в буфере есть место. Блокировка происходит только при попытке записи в полный буфер или чтения из пустого.
- Небуферизованные (
-
Закрытие канала (
close
)- Закрывать канал всегда должен отправитель. Попытка записи в закрытый канал вызовет панику.
- Чтение из закрытого канала не блокируется: оно немедленно возвращает нулевое значение для типа канала и
false
в качестве второго значения, что позволяет проверить, закрыт ли канал.v, ok := <-ch // ok будет false, если канал ch закрыт и пуст
-
Итерация по каналу с помощью
range
- Цикл
for v := range ch
автоматически считывает значения из канала до тех пор, пока он не будет закрыт. Это самый идиоматичный способ читать все данные из канала.
- Цикл
-
Мультиплексирование с
select
- Оператор
select
позволяет ожидать готовности нескольких каналов одновременно. Он блокируется, пока одна из операций (case
) не станет доступной. Если готовы несколько, выбирается одна случайным образом. - Блок
default
делаетselect
неблокирующим: если ни один канал не готов, выполняетсяdefault
.
- Оператор
-
Направленные каналы
- Тип канала можно ограничить только для отправки (
chan<- T
) или только для получения (<-chan T
). Это используется в функциях для обеспечения типобезопасности и ясности API: функция либо только производит данные, либо только потребляет их.
- Тип канала можно ограничить только для отправки (
-
Нулевое значение (
nil
) канала- Нулевое значение для канала —
nil
. Любая операция (чтение, запись, закрытие) наnil
-канале блокируется навсегда. Это частая причина дедлоков.
- Нулевое значение для канала —