什么是通道 channel?

”不要通过共享内存来通信 ,而应该通过通信来共享内存“ : 这句话什么意思呢?

类似于通信的管道, 虽然有传统共享数据同步机制,但go语言强烈建议我们使用 Channel 通道来实现goroutine 之间的通信

通道就是goroutine 之间的通道, 它可以让goroutine之间相互通信。

通道必须传递自己类型的数据

在这里插入图片描述

刚定义的通道 默认是nil的, 可以通过 make(chan int) 来创建

在这里插入图片描述
上图 证明通道传的是 内存地址

怎么使用 通道:读操作 + 写操作

data := <- a 从通道 a中取出值, 放到 data中

a <- data ; 将数据data放到 a 这个通道中

在这里插入图片描述

通道 channel 的注意点:

1 用于协程 ,传递消息
2 每个通道都有自己的数据类型 , nil通道,不能直接存储(即先定义,再创建)
3 使用通道传输数据:<-
chan <- data 发送数据到通道,向通道中写数据,
data<-chan 从通道中获取数据
4 阻塞: (必须 有读也有写, 阻塞是同时相互解除的)
发送数据: chan<-data写阻塞的,直到另一个协程读取数据才会解除阻塞,
读取数据: data:= <-chan 也是阻塞的, 直到另一端写出数据解除阻塞
5 本身 通道是同步的, 意味着 同一时间,只能有一条通道来操作。
6 通道是 协程之间的连接, 所以通道的发送和接收必须在不同的协程中。

死锁 : 没有读通道操作, 或者没有写通道操作 ,就会形成死锁

如何 关闭 通道:在子协程中关闭通道

在这里插入图片描述

在这里插入图片描述

对比发现 ,协程直接 也可能因为时间片原因进行抢占调度执行

缓冲通道

不带缓冲的通道: 只有读/写 会发生阻塞

带缓冲的通道: 数据先发送到缓冲区: 只有缓冲区满了 或者空了才会发生阻塞。

创建缓冲通道 只需要在后边 加上通道大小就可以了

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
通道都是按照队列的数据结构读取的

定向通道:单向通道

ch1 := make(<- chan int) 只能读不能写的通道
ch2 :=make(chan <- int) 只能写 , 不能读的通道
ch3 : =make(chan int) 双向 不带缓冲通道
ch4 : =make(chan int, 4) 双向 带缓冲通道

你可能会问: 既然 只是单向通道:那么又有什么暖用?

是的: 但向通道往往只是作为参数传递的 ,目的就是为了保护而已。
因为通道本来就是用于两个协程之间的通信的, 设置成单向的,往往用处不大

time包下与 通道相关的函数

主要就是 timer定时器, 可以让用户自己定义超时逻辑, 尤其是在 select 处理多个channel 的超时、单channel读写的超时等情况时尤为方便。

Timer是一次性的时间触发事件。Ticker 是按一定的时间间隔 持续触发事件的。

Timer 的触发方式:
一 : t := timer.NewTimer(d)
t := timer.AfterFunc(d,F)
c:=timer.After(d)
在这里插入图片描述

可以看到 C是一个只写通道,
在这里插入图片描述

在这里插入图片描述

Select 语句

select 是Go语言提供的一个控制结构(选择语句), 通过select 可以监听在channel上的数据流动

select和switch 语句非常像, 但是 select 会随机执行一个可运行的case, 如果没有case 可运行的话,有 default 会执行default, 没有的话, select将阻塞, 直到有case 可运行

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
这个时候 select 就进行随机选择case执行了

经过测试; select会优先执行 已就绪的语句