前言
Go语言的管道(通信)channel学习笔记
管道的特点
- 管道的本质是一种队列数据类型,数据是先进先出的
- 管道是线程安全的,多协程goroutine访问时无需加锁
- 管道定义时需要指定所存储数据的数据类型
声明一个管道
可读写管道
只读管道
只写管道
定义一个管道
- 管道是引用类型数据,必须初始化才能写入数据
- 管道变量实质上是一个指针,这个指针指向的是一个管道的真实地址
- 管道的容量不能自动增长
有缓冲的管道
1
| var 管道名 chan 数据类型 = make(chan 数据类型, 缓冲区大小)
|
无缓冲的管道
- 无缓冲的管道是同步的,在没有读取之前不能再次发送数据
- 无缓冲的管道缓冲区大小为0
1
| var 管道名 chan 数据类型 = make(chan 数据类型)
|
管道的数据发送与接收
- 同一管道中,数据的发送与发送、接收与接收之前是互斥的
向管道发送数据
从管道读取数据
不接收读取的数据
接收读取的数据
判断是否读取成功
ok
:读取成功返回true,读取失败返回false,读取失败说明管道已关闭
获取管道长度
获取管道容量
关闭管道
- 关闭管道后,不能再向管道中写入数据了,但是可以继续从管道中读取数据
遍历管道
- 遍历管道之前最好先关闭管道
- 先发送数据再读取数据
- 如果发送数据的个数大于或等于读取数据的个数,无论管道是否正常关闭,都可以正常读取数据
- 如果发送数据的个数小于读取数据的个数
- 如果管道已经关闭,则未超出部分能正常读取,超出部分的读取会得到数据类型的零值
- 如果管道没有关闭,则未超出部分能正常读取,超出部分的读取会报deadlock死锁错误
- 如果此时使用
for...range
的方式遍历管道,一定会报deadlock死锁错误
1 2 3 4
| close(管道名) for value := range 管道名 { ... }
|
select关键字
- 如果管道不清楚什么时候关,可以使用
select
关键字防止阻塞
select
中的case
必须是channel
操作
select
中的default
必须始终是可以运行的
- 如果
select
中有多个可以执行的case
子句,select
会随机选择一个可以执行的case
子句执行,其他的case
子句不会被执行
- 如果
select
中有default
子句,当所有case
都不能执行时,会跳到default
中执行
- 如果
select
中没有default
子句,当所有的case
都不能执行时,会阻塞并发生死锁
1 2 3 4 5 6
| select { case value := <-管道名: ... default: ... }
|
无限循环
1 2 3 4 5 6 7 8
| label: select { case value := <-管道名: ... default: break label } }
|
完成
参考文献
哔哩哔哩——尚硅谷
哔哩哔哩——郭宏志-老郭
哔哩哔哩——go圈里最会写js的奇淼