Как использовать оператор select для неблокирующей записи в канал?

Ответ

Да, оператор select — это идиоматичный способ выполнить неблокирующую запись в канал в Go.

Для этого в select добавляется ветка default. В этом случае, если операция записи в канал (case ch <- value:) не может быть выполнена немедленно (например, канал небуферизованный и нет читающей горутины, или буфер канала заполнен), будет исполнена ветка default.

Пример неблокирующей записи:

package main

import (
    "fmt"
    "time"
)

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

    // Первая запись успешна, т.к. в буфере есть место
    select {
    case ch <- 42:
        fmt.Println("Успешно записано значение 42")
    default:
        fmt.Println("Канал заблокирован, запись не удалась")
    }

    // Вторая запись не удастся, т.к. буфер уже заполнен
    select {
    case ch <- 100:
        fmt.Println("Успешно записано значение 100")
    default:
        fmt.Println("Канал заблокирован, запись не удалась")
    }
}

Важно: Если убрать ветку default, то select будет вести себя как обычная блокирующая операция записи: горутина остановится и будет ждать, пока запись в канал не станет возможной.