Ответ
Чтение из пустого буферизированного канала блокирует текущую горутину до тех пор, пока другой горутиной в канал не будет отправлено значение.
Это ключевое отличие от небуферизированного канала, который блокирует горутину-отправителя до тех пор, пока горутина-получатель не будет готова принять значение. В буферизированном канале отправка не блокируется, пока в буфере есть свободное место.
Пример блокировки при чтении:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
// Канал с буфером на 2 элемента
ch := make(chan int, 2)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("Горутина пытается прочитать из пустого канала...")
val := <-ch // <-- Блокировка здесь, т.к. канал пуст
fmt.Printf("Горутина успешно прочитала значение: %dn", val)
}()
fmt.Println("Основная программа ждет 2 секунды...")
time.Sleep(2 * time.Second)
fmt.Println("Основная программа отправляет значение в канал...")
ch <- 42 // Отправка значения разблокирует читающую горутину
wg.Wait() // Ожидаем завершения горутины
}
Чтение из закрытого канала
Если канал закрыт и пуст, операция чтения немедленно вернет нулевое значение для типа данных канала, а второй параметр ok
будет false
.
ch := make(chan int, 1)
ch <- 100
close(ch)
val, ok := <-ch // val = 100, ok = true (читаем последнее значение из буфера)
val, ok = <-ch // val = 0, ok = false (канал пуст и закрыт)