サンプルで学ぶ Go 言語:Closing Channels

チャネルを閉じるとそのチャネルにはもう値を送らないことを示せる。 これはチャネルの受信者に終わりを伝えるのに使える。

package main
import "fmt"

この例ではチャネル jobs を使って main() ゴルーチンからワーカーゴルーチンに仕事を送る。 ワーカーに実行してもらう仕事を送り終えると、チャネル jobs を閉じる。

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

ワーカーを起動する。 このゴルーチンは j, more := <-jobs の行で繰り返し jobs から値を受信する。 チャネルから2つ値を読み出しているのがキモだ。 チャネルが閉じられており、そのチャネルの値をすべて受信し終えているとき、more は false になる。 こうして最後の仕事を終えたことがわかるので、done を送り返せる。

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

チャネル jobs を通じて3つの仕事をワーカーに送り、その後チャネルを閉じる。

    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 をチャネルに適用するというアイデアにつながる。

次の例:Range over Channels