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

Ответ

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

Принцип работы (рандеву):

  • Отправка в такой канал (ch <- data) блокирует горутину-отправителя до тех пор, пока другая горутина не будет готова принять данные из этого же канала.
  • Чтение из канала (<-ch) блокирует горутину-получателя до тех пор, пока другая горутина не отправит данные в этот канал.

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

Пример:

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

go func() {
    fmt.Println("Горутина: готовлюсь отправить данные...")
    ch <- 42 // Блокировка до тех пор, пока main не будет готова принять
    fmt.Println("Горутина: данные отправлены!")
}()

time.Sleep(1 * time.Second) // Даем горутине время запуститься
fmt.Println("Main: готовлюсь принять данные...")
val := <-ch // Блокировка до получения данных, одновременно разблокирует горутину
fmt.Printf("Main: данные получены: %dn", val)

Ключевые особенности и использование:

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

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