Go Em Exemplos: Closing Channels

Fechar um canal indica que mais nenhum valor será enviado para ele. Isto pode ser útil para comunicar a finalização dos recebimentos.

package main
import "fmt"

Neste exemplo será usado um canal tarefas para comunicar tarefa a ser executada pela função main() para uma worker goroutine. Ao não ter mais tarefas para a worker, o canal será fechado com close.

func main() {
    tarefas := make(chan int, 5)
    pronto := make(chan bool)

Aqui está a worker goroutine. Ela repetidamente recebe do canal tarefas com t, mais := <-tarefas. Nesta forma de recebimento de dois valores, o valor mais será falso se tarefas foi fechado e todos os valores do canal já tiverem sido recebidos. Isto é utilizado para notificar ao done quando todas as tarefas já foram executadas. Importante notar que tarefas é um canal buffered.

    go func() {
        for {
            t, mais := <-tarefas
            if mais {
                fmt.Println("received job", t)
            } else {
                fmt.Println("received all tarefas")
                pronto <- true
                return
            }
        }
    }()

Isto envia 3 tarefas para a worker goroutine pelo canal tarefas e então o fecha.

    for t := 1; t <= 3; t++ {
        tarefas <- t
        fmt.Println("sent job", t)
    }
    close(tarefas)
    fmt.Println("sent all tarefas")

A execução é aguardada utilizando a sincronização, como apresentado anteriormente.

    <-pronto
}
$ go run closing-channels.go 
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs

A ideia de canais fechados leva naturalmente ao próximo exemplo: range em canais.

Próximo exemplo: Range over Channels.