

Go基础系列:双层channel用法示例
source link: https://studygolang.com/articles/16445?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Go channel系列:
双层通道的解释见 Go的双层通道
以下是一个双层通道的使用示例。注意下面的示例中使用了"信号通道"(Signal channel),但这里的信号通道是多余的,仅仅只是为了介绍。
信号通道不用来传递数据,而是用来传递消息,用来产生可读、可写的事件,以便让select选中某个分支。产生消息事件的方式有多种,比如直接关闭通道、发送false/true布尔值等等。
package main import ( "fmt" "time" ) func main() { // 定义双层通道cc cc := make(chan chan int) times := 5 for i := 1; i < times+1; i++ { // 定义信号通道f f := make(chan bool) // 每次循环都在双层通道cc中生成内层通道c // 并通过信号通道f来终止f1() go f1(cc, f) // 从双层通道cc中取出内层通道ch // 并向ch通道发送数据 ch := <-cc ch <- i // 从ch中取出数据 for sum := range ch { fmt.Printf("Sum(%d)=%d\n", i, sum) } // 每个循环睡眠一秒钟 time.Sleep(time.Second) // 每次循环都关闭信号通道f close(f) } } // 双层通道cc用来生成内层通道c // 并使用信号通道f来终止函数f1() func f1(cc chan chan int, f chan bool) { c := make(chan int) cc <- c defer close(c) sum := 0 select { // 从内层通道中取出数据,计算和,然后发回内层通道 case x := <-c: for i := 0; i <= x; i++ { sum = sum + i } // goroutine将阻塞在此,直到数据被读走 c <- sum // 信号通道f可读时,结束f1()的运行 // 但因为select没有在for中,该case分支用不上 case <-f: return } }
上面的示例中,函数f1()两个参数,一个是双层通道cc,一个是信号通道f。f1()中首先生成了一个通道c,并发送给了双层通道cc,使得main()中可以从cc中取得这个内层通道c,并向其发送数据。
回到f1()中,select最初会被阻塞,因为内层通道c和信号通道f都没有数据可读。由于main()可以取得内层通道c,并向其发送数据,使得f1()中的select第一个case分支被选中,该分支会计算发送的整数之前的总和,并将计算结果重新发送给内层通道c,让main()可以取得这个计算结果。
上面的示例中有几个细节需要注意:
- 在f1()中必须关闭内层通道c,因为main()中的range迭代一个未关闭的通道会一直阻塞,而且每次调用f1()都会重新创建c通道。
- 上面的信号通道其实没有起到任何作用。
- f1()中的select必须不能放进for循环。因为f1()将数据发回c之后,如果在for中,发f()所在的goroutine将阻塞在select上,由于c通道还没有关闭,这会导致main goroutine因range迭代操作而阻塞,也就是说所有goroutine都被阻塞了,出现了死锁。
所以,当在select中有发送操作的时候,很可能会出现死锁现象。这时, 要么为select加上default,要么为select加上超时时间,要么select不要放在for循环中 。
Recommend
-
31
双层玻璃猫爪杯 印花款 39.9元包邮(需用券),来自什么值得买甄选出的天猫精选优惠产品,汇聚数十万什么值得买网友对该网购产品的点评。
-
22
两个链用了相同的启动程序, 是在以太坊最新代码的基础上修改的,每个节点都会连接本网的全节点和对方网络的全节点,节点提供的功能是本网全节点、本网轻节点server、对方网络轻节点client的功能。实现两个网的跨链,可以想象成主网和测试...
-
3
邹传伟:深入分析公链经济体的双层耦合问题 鸵鸟区块链要闻 2021-04-02 15:25 2436 摘要: 底层经济体对应着共识...
-
16
本文约 2420 字、8 张图表,需 5 分钟阅读 如果有朋友留意过我们2019年以及2020年年度回顾之显示器篇的话,可能对于里面讲述LCD技术...
-
10
首页 > 文章详情 姚前:数字货币一定会走向智能货币 双层架构不必排斥以太坊等 数字金融资产研究中心 1天前 5月29日-30...
-
8
推荐一部真人秀:双层公寓(都会男女) 2021-07-12 ...
-
8
国内首座 双层四线跨江铁路桥主跨合龙 来源:
-
7
Linux中cron命令的16个基础用法及示例 ...
-
4
迭代器(Iterator)简介迭代器(Iterator)是一种接口(对象的一个属性方法),为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署了(Iterator)接口,就可以完成...
-
6
lambda表达式简明扼要的以流水线的方式去处理集合内的数据,可以很轻松的完成过滤、分组、收集、归约这类操作...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK