Go by Example: Closing Channels

Closing un canal indica que no se enviarán más valores en él. Esto puede ser útil para comunicar la finalización a los receptores del canal.

package main
import "fmt"

En este ejemplo utilizaremos un canal jobs para comunicar trabajo a realizar desde la goroutine main() a una goroutine trabajadora. Cuando no tengamos más trabajos para el trabajador, cerraremos el canal jobs.

func main() {
    jobs := make(chan int, 5)
    done := make(chan bool)

Aquí está la goroutine trabajadora. Recibe repetidamente de jobs con j, more := <-jobs. En esta forma especial de recepción de 2 valores, el valor more será false si jobs ha sido cerrado y todos los valores en el canal ya han sido recibidos. Utilizamos esto para notificar en done cuando hemos terminado todos nuestros trabajos.

    go func() {
        for {
            j, more := <-jobs
            if more {
                fmt.Println("received job", j)
            } else {
                fmt.Println("received all jobs")
                done <- true
                return
            }
        }
    }()

Esto envía 3 trabajos al trabajador a través del canal jobs, luego lo cierra.

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

Esperamos al trabajador utilizando el enfoque de sincronización que vimos anteriormente.

    <-done

Leer de un canal cerrado se realiza inmediatamente, devolviendo el valor cero del tipo subyacente. El segundo valor de retorno opcional es true si el valor recibido fue entregado por una operación de envío exitosa al canal, o false si fue un valor cero generado porque el canal está cerrado y vacío.

    _, ok := <-jobs
    fmt.Println("received more jobs:", ok)
}
$ 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
received more jobs: false

La idea de canales cerrados nos lleva naturalmente a nuestro próximo ejemplo: range sobre canales.

Siguiente ejemplo: Range over Channels.