什么是通道 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会优先执行 已就绪的语句