Ответ
Буферизованный канал (созданный с размером больше 0, например make(chan int, 100)
) блокирует горутину в двух ситуациях:
При отправке в переполненный канал.
Если буфер канала уже заполнен (в нем находится 100 элементов), следующая операция отправкиch <- value
заблокирует текущую горутину до тех пор, пока другая горутина не освободит место, прочитав данные из канала.При чтении из пустого канала.
Если буфер канала пуст, операция чтения<-ch
заблокирует текущую горутину до тех пор, пока другая горутина не отправит данные в этот канал.
Примеры блокировок:
package main
import (
"fmt"
"time"
)
func main() {
// Канал с буфером на 3 элемента
ch := make(chan int, 3)
// --- Сценарий 1: Блокировка при отправке ---
fmt.Println("Заполняем буфер...")
ch <- 1
ch <- 2
ch <- 3
fmt.Println("Буфер полон. Следующая отправка заблокируется.")
go func() {
time.Sleep(2 * time.Second)
value := <-ch // Через 2 секунды освобождаем место
fmt.Printf("nПрочитано значение: %dn", value)
}()
ch <- 4 // Эта строка заблокирует выполнение main на 2 секунды
fmt.Println("Отправка значения 4 разблокирована и завершена.")
// --- Сценарий 2: Блокировка при чтении ---
// К этому моменту в канале [2, 3, 4]
<-ch // Читаем 2
<-ch // Читаем 3
<-ch // Читаем 4
fmt.Println("nКанал пуст. Следующее чтение заблокируется.")
go func() {
time.Sleep(2 * time.Second)
ch <- 5 // Через 2 секунды отправляем значение
fmt.Println("nОтправлено значение 5 в канал")
}()
value := <-ch // Эта строка заблокирует выполнение main на 2 секунды
fmt.Printf("Чтение разблокировано. Прочитано значение: %dn", value)
}
Для сравнения, небуферизованный канал (make(chan int)
) — это частный случай буферизованного с размером 0. Он блокируется при каждой операции отправки или чтения, пока на другом конце не будет готова принимающая или отправляющая сторона.