以範例學 Go:關閉通道

關閉 通道表示不再傳送任何值。這在對通道的接收器傳達完成訊息時很有用。

package main
import "fmt"

在本例中,我們將使用 jobs 通道傳送工作,從 main() goroutine 到一個工作人員 goroutine。當我們的 worker 沒有其他工作時,我們就會 close jobs 通道。

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

以下是工作人員的 goroutine。它會重複接受 jobs 中的 j 和 more:<-jobs。在接收的這個特殊的雙值形式中,如果 jobs 已 close,且通道中所有值都已接收,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

從關閉的通道中讀取會立即成功,傳回底層類型的零值。選擇性的第二個傳回值為 true,表示接收到的值是由成功的傳送操作傳送到通道,或為 false,表示它是因為通道已關閉且為空而產生的零值。

    _, 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

封閉通道的想法自然會想到我們的下一個範例:巡訪通道。

下一個範例:巡訪通道