首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

大道如青天,协程来通信,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang通道channel的使用EP14

众所周知,Go lang的作用域相对严格,数据之间的通信往往要依靠参数的传递,但如果想在多个协程任务中间做数据通信,就需要通道(channel)的参与,我们可以把数据封装成一个对象,然后把这个对象的指针传入某个通道变量中,另外一个协程从这个通道中读出变量的指针,并处理其指向的内存对象。

通道的声明与创建

这里注意,通道声明之后还需要进行创建。

也可以通过海象操作符声明并创建:

程序返回:

如此,一个类型为整形的通道就创建好了。

此外,通道是引用数据类型:

程序返回:

可以看到,在test1函数内和main函数内通道的地址是一样的,所以他们指向的都是同一个通道。

通道的使用

通道创建之后,即可以在协程之间充当桥梁:

这里我们声明一个函数job,把通道作为参数传递进去,注意这里参数类型除了声明通道本身以外,还得声明通道具体的数据类型。

随后在main函数中,可以理解为主协程,创建通道ch1,执行开启协程任务job,在job函数内,往通道内传递数字1

接着,主协程获取通道内由job协程传递的数据:

藉此,就完成了数据的传递。

这里需要注意通道的调用语法:

同步阻塞

这里需要注意的是,通道无论是写入还是读取,都是同步阻塞机制。即当有协程对通道进行操作的时候,其他协程都处于“等待”状态,说白了,就是在“排队”,在之前的一篇:并发与并行,同步和异步,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang并发编程之GoroutineEP13[1],我们要么通过sync.WaitGroup来阻塞主协程,或者通过time.Sleep(time.Second)方法来阻塞,就是怕主协程提前执行完,早成子协程来不及执行。

而通道的出现,就间接帮我们实现了“阻塞”主协程的目的。

比如,多个协程任务操作一个变量:

这里job1和job2两个协程任务同时异步执行,操作number变量,累加后往通道中写入,程序返回:

理论上,如果是并发执行,返回值应该是20或者10,但由于通道的存在,造成协程任务阻塞,变回了同步执行,所以返回了30。

同时,我们需要注意死锁问题,如果一个协程任务在一个通道上发送数据,那么其他的协程任务应该接收数据,如果这种情况不发生,那么程序将在运行时出现死锁。

换句话说,你发送了,就得有人接收,只发不接,或者只收不发,都会变成死锁。

此外,协程任务可以通过close(ch)方法来关闭通道:

这里将0到2写入chl通道,然后关闭通道。主函数里有一个死循环。类似while,它轮询通道是否在发送数据后,使用变量ok进行判断。如果ok是假的,则意味着通道关闭,因此循环结束,否则将会继续进行无限轮询。

select关键字

select 是 Go lang里面的一个流程控制结构,和switch关键字差不多,但是select会随机执行一个可运行的通道通信,如果没有通道通信可运行,它将阻塞,直到有通道通信可运行:

这里select会随机选择一个可运行的通道通信逻辑,可能是ch1通道,也有可能是ch2通道:

结语

综上,Golang的通道其实就是将协程任务进行隔离,编写并发逻辑时,关注通道即可,说白了,Golang的通道就是Python多进程通信中的管道,Golang虽然没有显性的多进程调用,但其协程调度底层就是多进程之间的通信,因为只有多进程才可能利用CPU的多核资源。

引用链接

并发与并行,同步和异步,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang并发编程之GoroutineEP13:https://v3u.cn/a_id_240

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20221225A015OP00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

相关快讯

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券