Ответ
Каналы в 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)