Какую модель/парадигму конкурентности реализуют каналы в Go?

Ответ

Каналы в Go реализуют модель конкурентности на основе обмена сообщениями, которая является практическим воплощением теоретической модели CSP (Communicating Sequential Processes — Взаимодействующие последовательные процессы).

Основная философия этого подхода выражена в слогане Go:

"Do not communicate by sharing memory; instead, share memory by communicating."
(Не общайтесь через разделяемую память; вместо этого, разделяйте память через общение.)

Ключевые характеристики:

  • Безопасность: Каналы позволяют горутинам безопасно передавать данные друг другу без необходимости в явных блокировках (мьютексах), что снижает риск состояний гонки.
  • Синхронизация: Отправка и получение данных из канала являются блокирующими операциями (для небуферизованных каналов), что само по себе служит механизмом синхронизации горутин.
  • Типы каналов:
    • Небуферизованные (синхронные): ch := make(chan int). Отправитель блокируется, пока получатель не будет готов принять данные.
    • Буферизованные (асинхронные): ch := make(chan int, 10). Отправитель блокируется, только если буфер полон.
  • Гарантия happens-before: Успешная отправка в канал происходит до соответствующего получения из этого канала. Это одна из фундаментальных гарантий модели памяти Go.

Пример:

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

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

// main блокируется, пока не получит значение из канала
message := <-ch
fmt.Println(message)