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](channel-synchronization),
// 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.