一 有缓冲管道与无缓冲管道
上一篇协程最后的同步时用无缓冲管道进行同步,无缓冲就是管道没有容量,放了东西必须拿走才能再次放,否则就阻塞。有缓冲管道可以指定管道容量,当管道满了,才会进行阻塞。使用有缓冲管道对协程进行通信,就会有异步的问题。
无缓冲管道的创建 ch := make(chan int)
有缓冲管道的创建 ch := make(chan int,3)//管道容量3
二 单向管道
单向管道就是只能读或者只能写
package main
import (
"fmt"
)
func readNum(ch <-chan int){
for num := range ch{
fmt.Printf("read num=%d\n",num)
}
}
func writeNum(ch chan<- int){
num := 123
fmt.Printf("write num=%d\n",num)
ch<- num
close(ch)
}
func main() {
ch := make(chan int)
//var wrch chan<- int = ch//只写
//var rach <-chan int = ch//只读
go writeNum(ch)
readNum(ch)
fmt.Println("main")
}
单向管道不能转换为双向,双向可以转换为单向。
三 select多路复用与超时机制
select是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收
select随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该总是可运行的
package main
import (
"fmt"
)
func readNum(ch <-chan int,quit <-chan bool){
for {
select{
case num :=<- ch:
fmt.Printf("read num=%d\n",num)
case <- quit:
fmt.Println("quit")
return
}
}
}
func main() {
ch := make(chan int)
quit := make(chan bool)
go func (ch chan<- int,quit chan<- bool){
var num int
for i:= 1;i<5;i++{
num= i*i*i
ch<- num
}
quit<- true
close(quit)
close(ch)
}(ch,quit)
readNum(ch,quit)
}
超时机制
package main
import (
"fmt"
"time"
)
func readNum(ch <-chan int){
for {
select{
case num :=<- ch:
fmt.Printf("read num=%d\n",num)
case <- time.After(3*time.Second)://超过三秒没有响应,自动退出
fmt.Println("quit")
return
}
}
}
func main() {
ch := make(chan int)
go func (ch chan<- int){
var num int
for i:= 1;i<5;i++{
num= i*i*i
ch<- num
}
}(ch)
readNum(ch)
}
结果,当输出后,没有响应,自动打印quit,结束阻塞状态