Go в примерах: Закрытие каналов (Closing Channels)

Закрытие канала показывает, что больше нельзя будет отправить значения через него. Это может быть полезно для сообщения о завершении приёмникам канала.

package main
import "fmt"

В этом примере используется канал jobs для сообщения о завершении работы от горутины main() рабочей горутине. Когда больше нет задач для рабочей горутины закрываем канал jobs.

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

Это рабочая горутина. Она постоянно получает данные из jobs посредством j, more := <-jobs. В этой специальной форме получения данных с 2-мя значениями, значение more будет false если jobs был закрыт и все значения в канале уже были получены. Мы используем этот подход для уведомления на done в момент, когда обработаны все задачи.

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

Отправляем 3 задачи рабочей горутине через канал jobs и закрываем его.

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

Ждем рабочую горутину используя подход синхронизации, который был рассмотрен ранее.

    <-done
}
$ 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

Идея закрытых каналов естественно приводит к следующему примеру: перебор значений каналов.

Следующий пример: Перебор значений каналов (Range over Channels).