关闭channel

您可以使用close(chan)关闭通道。
关闭通道的主要目的是为了通知工作者协程它们的工作已经完成了,它们可以退出了。
这可以确保您不会泄漏协程。

关闭通道使迭代它的range循环结束:

package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan string)
go func() {
for s := range ch {
fmt.Printf("received from channel: %s\n", s)
}
fmt.Print("range loop finished because ch was closed\n")
}()
ch <- "foo"
close(ch)
time.Sleep(1 * time.Second) // 花1秒钟等待协程执行完毕
}
------------Output------------
received from channel: foo
range loop finished because ch was closed

从已关闭的通道中接收数据会立即返回零值:

func main() {
ch := make(chan string)
close(ch)
v := <-ch
fmt.Printf("Receive from closed channel immediately returns zero value of the type: %#v\n", v)
}
-----------Output-----------
Receive from closed channel immediately returns zero value of the type: ""

在接收时还可以检测通道是否已关闭:

func main() {
ch := make(chan int)
go func() {
ch <- 1
close(ch)
}()
v, isClosed := <-ch
fmt.Printf("received %d, is channel closed: %v\n", v, isClosed)
v, isClosed = <-ch
fmt.Printf("received %d, is channel closed: %v\n", v, isClosed)
}
-----------Output-------------
received 1, is channel closed: true
received 0, is channel closed: false

多次关闭通道会引发恐慌:

func main() {
ch := make(chan string)
close(ch)
close(ch)
}
-----------Output-------------
panic: close of closed channel
goroutine 1 [running]:
main.main()
/tmp/src/main.go:6 +0x5e
exit status 2

向已关闭的通道放数据也会引发恐慌:

func main() {
ch := make(chan int)
close(ch)
ch <- 5 // panics
}
-----------Output------------
panic: send on closed channel
goroutine 1 [running]:
main.main()
/tmp/src/main.go:6 +0x6a
exit status 2