Go语言那些事儿之管道的关闭

举报
Regan Yue 发表于 2021/08/11 15:49:18 2021/08/11
【摘要】 Go语言那些事儿之管道的关闭之前我们提到了怎么定义管道,讲了管道的读取和写入。那么今天我们就来讲一讲管道的关闭。先来看一个简单的例子:func main() { ch := make(chan int,10) for i := 0;i < 5;i++{ ch <- i*i } close(ch) for x:= range ch { fmt.Println(x) }}先思考一下它会输出...

Go语言那些事儿之管道的关闭

之前我们提到了怎么定义管道,讲了管道的读取和写入。那么今天我们就来讲一讲管道的关闭。

先来看一个简单的例子:

func main() {
	ch := make(chan int,10)
	for i := 0;i < 5;i++{
		ch <- i*i
	}
	close(ch)

	for x:= range ch {
		fmt.Println(x)
	}
}

先思考一下它会输出什么?

没错它的输出结果是:

0
1
4
9
16

这段的代码就是定义一个管道,然后遍历零到四,将零到四的平方塞入管道。我们知道这个管道定义时,被赋予了10的缓存能力,所以能够缓存10个单位的数据。而我们这里只需要存5个单位,你会想是不是还有5个单位是空闲的?是的。

下面我们再看一看多个协程并发读写管道:

func main()  {
	ch := make(chan int,10)

	go func() {
		for i:=0;i<5;i++{
			ch <- i * i
			fmt.Println("写入",i*i)
			time.Sleep(1 * time.Second)

		}
        // The close built-in function closes a channel, which must be either
		// bidirectional or send-only. It should be executed only by the sender,
        // never the receiver, and has the effect of shutting down the channel after
        // the last sent value is received. After the last value has been received
        // from a closed channel c, any receive from c will succeed without
        // blocking, returning the zero value for the channel element. The form
        //	x, ok := <-c
        // will also set ok to false for a closed channel.
		close(ch)
		fmt.Println("管道已关闭,写入协程结束")
	}()
	go func() {
		for x:= range ch{
			fmt.Println("读出",x)
		}
		fmt.Println("读取协程结束")
	}()

	time.Sleep(6 * time.Second)
	fmt.Println("GAME OVER")
}

运行结果是:

写入 0
读出 0
读出 1
写入 1
写入 4
读出 4
写入 9
读出 9
写入 16
读出 16
读取协程结束
管道已关闭,写入协程结束
GAME OVER

这段代码的作用是建立一个缓存能力为10的管道,建立两条协程。一条协程用来将零到四的平方写入管道,写完之后关闭管道。另一条协程是用来将管道内的数据读出。

由于两条协程是并发的,所以一条协程往管道里写入一条数据,马上另一条协程就往管道里读取一条数据。这里那条写入数据的协程关闭了管道,那么就会通知那边不需要再继续从管道中读取数据了,那么另外一条协程就不会往管道里面读取数据了。如果没有close(ch),也就是不关闭管道,那么另一条协程就会不断读取管道,直到主协程正常结束,那条子协程才会结束。

我们需要注意,内建函数close函数是用来关闭通道的,并且只有双向的和仅发送的管道才能被关闭。

还有一点需要注意的是,这个close函数需要由发送方执行,而不是由接收方执行。从一个关闭的通道接收完最后一个值后,从该管道接收的任何值都将成功,不会阻塞,并返回零值。但是对于x, ok := <-c,将会为关闭的管道的ok值赋予false值。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。