美文网首页
go语言的channel(管道)

go语言的channel(管道)

作者: 梁帆 | 来源:发表于2021-03-15 00:02 被阅读0次

为什么需要channel?

前面使用全局变量加锁同步来解决goroutine的通讯,但不完美。

(1)主线程在等待所有goroutine全部完成的时间很难确定,我们这里设置10秒,仅仅是估算。

(2)如果主线程休眠时间长了,会加长等待时间,如果等待时间短了,可能还有goroutine处于工作状态,这时也会随主线程的退出而销毁。

(3)通过全局变量加锁同步来实现通讯,也并不利于多个协程对全局变量的读写操作。

(4)上面种种分析都在呼唤一个新的通讯机制——channel

一、channel的介绍

1、channel本质上就是一种数据结构——队列。

2、数据是先进先出。

3、线程安全,多goroutine访问时,不需要加锁,就是说channel本身就是线程安全的。

4、channel是有类型的,一个string的channel只能存放string类型数据。

示意图

二、管道的基本使用

1、定义/声明channel

channel的定义和声明

2、初始化

channel的初始化

3、向channel中写入(存放)数据

向channel中写入(存放)数据

4、channel使用的注意事项

(1)channel中只能存放指定的数据类型。

(2)channel的数据放满后,就不能再放入了。

(3)如果从channel取出数据后,可以继续放入。

(4)在没有使用协程的情况下,如果channel数据取完了,再取,就会报dead lock。

5、channel的遍历和关闭

关闭和遍历

关闭例程如下:

关闭例程

遍历例程如下:

关闭例程

三、channel的案例演示

1、创建一个intChan,最多可以存放3个int,演示存3个数据到intChan,然后再取出这3个int:

示例

2、创建一个mapChan,最多可以存放10个map[string]string的键值对,演示写入和读取:

示例

3、创建一个catChan,最多可以存放10个Cat结构体变量,演示写入和读取的用法:

示例

5、创建一个allChan,最多可以存放10个任意数据类型变量,演示写入和读取的用法:

示例

四、管道的使用细节和注意事项

1、channel可以声明为只读或者只写性质

只写的管道 只读的管道

2、channel只读和只写的最佳实践案例

最佳写法

main方法中,有send和recv两个协程。send中需要穿恶毒管道ch参数,如果我们希望它是只写的,可以在定义send函数的时候写明参数ch chan<- int,这样ch在函数内就是只写而不能被读取了。这样的做法可以防止误操作。recv协程同理,我们希望管道ch是只读的,可以在定义recv函数的时候写明参数ch <-chan int

3、使用select可以解决从管道取数据的阻塞问题。

示例上半部 示例下半部 输出

4、goroutine中使用recover,解决协程中出现panic,导致程序崩溃问题。

如果我们起了一个协程,但是这个协程出现了panic,如果这个协程出现了panic,如果我们没有捕获panic,就会造成整个程序崩溃,这时我们可以在goroutine中使用recover来捕获panic,进行处理,这样即使这个协程发生了问题,主线程仍然不受影响,可以继续执行。

示例

这个示例中,画红线的这一行代码将来在执行时就会出错,因为map还没有用make分配空间就给它赋值了,最后test()协程会出错,进而造成整个主线程的崩溃停止运行。

修改后

这里用defer和recover解决了这个问题,出错了,返回输出一个错误即可,整个主线程还在继续执行。

输出

输出如下所示,虽然test()发生了错误,但是主线程依旧继续执行。

相关文章

网友评论

      本文标题:go语言的channel(管道)

      本文链接:https://www.haomeiwen.com/subject/mflqcltx.html