Как работает запись в буферизированный канал в Go?

Ответ

Буферизированный канал создается с указанием размера буфера: make(chan T, capacity), где capacity > 0.

Поведение при записи в такой канал зависит от того, заполнен ли его буфер:


  1. Если в буфере есть место:

    Запись происходит немедленно и не блокирует горутину. Значение помещается в очередь внутри канала, и горутина продолжает свое выполнение.



  2. Если буфер заполнен:

    Запись блокирует текущую горутину. Она будет ждать до тех пор, пока другая горутина не прочитает данные из канала, освободив тем самым место в буфере.


Пример:

package main

import "fmt"

func main() {
    // Канал с буфером на 2 элемента
    ch := make(chan int, 2)

    fmt.Println("Отправляем 1...")
    ch <- 1 // Не блокируется, буфер: [1]

    fmt.Println("Отправляем 2...")
    ch <- 2 // Не блокируется, буфер: [1, 2]

    fmt.Println("Буфер полон. Отправляем 3...")
    // Следующая строка вызовет deadlock, так как буфер полон,
    // а читающей горутины нет. Программа заблокируется навсегда.
    ch <- 3 // Блокируется

    fmt.Println("Эта строка никогда не будет выполнена")
}

Ключевой момент: Буферизация позволяет горутинам-отправителям и горутинам-читателям работать асинхронно до тех пор, пока буфер не заполнится или не опустеет. Это может значительно повысить производительность, снижая количество блокировок.