Как работает чтение из небуферизированного канала в Go и каковы его особенности?

Ответ

Чтение из небуферизированного канала — это синхронная операция, которая блокирует текущую горутину до тех пор, пока другая горутина не отправит данные в этот же канал. Этот механизм также называют "рандеву", так как отправитель и получатель должны "встретиться" для совершения операции.

// Создаем небуферизированный канал
ch := make(chan int)

go func() {
    // Эта горутина заблокируется здесь, пока другая горутина
    // не будет готова прочитать данные из канала ch.
    ch <- 42
}()

// Основная горутина блокируется здесь, ожидая данные из канала ch.
value := <-ch

fmt.Println("Получено значение:", value) // Выведет: 42

Ключевые особенности:

  1. Блокировка при отправке: Горутина, отправляющая данные (ch <- data), блокируется, пока другая горутина не будет готова их принять (<-ch).
  2. Блокировка при чтении: Горутина, читающая данные (<-ch), блокируется, пока другая горутина не отправит данные в канал.
  3. Риск взаимной блокировки (deadlock): Если горутина пытается отправить данные, но нет ни одной другой горутины, готовой их принять (или наоборот), программа зависнет и завершится с ошибкой fatal error: all goroutines are asleep - deadlock!.
  4. Неблокирующее чтение: Для попытки чтения без блокировки можно использовать конструкцию select с веткой default.