Ответ
Синхронный (или небуферизованный) канал в Go — это канал, созданный без указания емкости буфера: make(chan T)
.
Его ключевая особенность — блокировка операций отправки и получения до тех пор, пока на другом конце канала не будет готова парная операция. Этот механизм называется "рандеву" (rendezvous), так как отправитель и получатель должны "встретиться" для совершения обмена данными.
- Отправка (
ch <- data
) блокирует горутину-отправителя, пока другая горутина не будет готова прочитать из этого канала (<-ch
). - Чтение (
<-ch
) блокирует горутину-получателя, пока другая горутина не отправит данные в этот канал.
Пример:
package main
import (
"fmt"
"time"
)
func main() {
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)
}
Ключевые отличия от буферизованных каналов
Характеристика | Синхронный канал (make(chan T) ) | Буферизованный канал (make(chan T, N) ) |
---|---|---|
Емкость | 0 | N > 0 |
Блокировка отправки | Всегда, до появления получателя. | Только когда буфер полон. |
Блокировка получения | Всегда, до появления отправителя. | Только когда буфер пуст. |
Основное назначение | Синхронизация горутин, гарантированная передача данных. | Буферизация данных, сглаживание разницы в скорости между производителем и потребителем. |
Синхронные каналы часто используются для сигнализации о завершении работы или для управления потоком выполнения, когда важно знать, что сигнал был получен.