Как происходит передача данных в небуферизированный (синхронный) канал в Go?

Ответ

Небуферизированный канал (или синхронный канал) — это канал с нулевой емкостью, создаваемый как make(chan T). Он используется для прямой синхронизации между горутинами.

Механизм "Рандеву"

Передача данных через небуферизированный канал — это синхронная операция, требующая одновременного участия и отправителя, и получателя. Этот механизм называется "рандеву" (rendezvous).

  1. Отправка: Горутина, отправляющая данные (ch <- data), блокируется и ждет, пока другая горутина не будет готова принять эти данные.
  2. Получение: Горутина, читающая данные (data := <-ch), блокируется и ждет, пока другая горутина не отправит данные в этот канал.

Передача данных происходит только тогда, когда и отправитель, и получатель готовы. В этот момент значение копируется напрямую от отправителя к получателю, после чего обе горутины разблокируются и продолжают выполнение.

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

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

// main горутина блокируется здесь, пока другая горутина не отправит данные
val := <-ch // Происходит "рандеву", обе горутины разблокируются

fmt.Println(val) // 42

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

  • Гарантия доставки: Отправитель может быть уверен, что сообщение было получено, как только его операция отправки завершилась.
  • Синхронизация: Это мощный примитив для синхронизации выполнения двух горутин в определенной точке.
  • Отсутствие буфера: Канал не хранит значения, он лишь служит точкой для их прямой передачи.