golang: 读取已关闭的缓冲型channel的表现

 

最近看到一段代码逻辑很奇怪:返回一个已关闭的 channel 给其他 goroutine 读取使用。这让我产生了一个疑问,很多文章说“从已关闭的 chan 读数据永远不会阻塞,一律返回空值”,为什么还会对channel进行关闭后返回?

代码如下:

func gen(nums ...int) <-chan int {
	out := make(chan int)
	go func() {
		for _, n := range nums {
			out <- n
		}
		close(out)
	}()
	return out
}

  

 

实际测试后发现,“从已关闭的 chan 读数据永远不会阻塞,一律返回空值”这句话并不正确。下面的测试代码在关闭 channel 之后继续对 channel 读取,还是可以读取到缓冲区的结果。

结论是:从已关闭的 channel 接收数据,返回已缓冲数据或零值。

测试代码如下:

package main

import (
	"time"
)

var ch chan int

func f() {
	ch = make(chan int, 5)
	println("start")
	for i := 1; i < 5; i++ {
		ch <- i
	}
	close(ch)
	println("close")
}

func main() {
	go f()

	time.Sleep(time.Second * 1)
	println("closed")

	for c := range ch {
		println(c)
	}
}

  输出:

 

posted @ 2020-01-08 17:02  impluse  阅读(2344)  评论(0编辑  收藏  举报