Go Em Exemplos: Non-Blocking Channel Operations

Envios e recebimentos básicos nos canais, são bloqueantes. No entanto, é possível usar o select com uma cláusula default para implementar envio e recebimentos non-blocking e até non-blocking select de multiplos casos.

package main
import "fmt"
func main() {
    messages := make(chan string)
    signals := make(chan bool)

Aqui está um recebimento não bloqueante. Se um valor estiver disponível em messages o select prosseguirá com o case que tem o <-messages. Se não, presseguirá com o case padrão ou default.

    select {
    case msg := <-messages:
        fmt.Println("received message", msg)
    default:
        fmt.Println("no message received")
    }

Um send não bloqueante funciona de maneira similar. Aqui, msg não pode ser enviado para o canal messages, justamente porque o canal não tem buffer e não tem um recebimento. Portanto, o case default será executado.

    msg := "hi"
    select {
    case messages <- msg:
        fmt.Println("sent message", msg)
    default:
        fmt.Println("no message sent")
    }

É possível utilizar multiplos cases acima da clausula default. Aqui está uma tentativa de recebimento não bloqueante em ambos os canais messages and signals.

    select {
    case msg := <-messages:
        fmt.Println("received message", msg)
    case sig := <-signals:
        fmt.Println("received signal", sig)
    default:
        fmt.Println("no activity")
    }
}
$ go run non-blocking-channel-operations.go 
no message received
no message sent
no activity

Próximo exemplo: Closing Channels.