关闭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

最后更新于