美文网首页
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