本篇文章主要介绍Go语言 管道:判断管道关闭、单向通道及多管道协同工作内容和示例。
目录
如何判断管道关闭
需要知道一个管道的状态,如果已经关闭了,读不会有问题,会返回零;
但是如果继续写,会有崩溃风险。
可以使用map时,使用的ok-idom模式判断,如下:
map ==> v, ok := m1[0]
channel ==> v, ok := <-numChan
示例如下:
package main
import "fmt"
func main() {
numChan := make(chan int, 10)
// 写
go func() {
for i:= 0; i< 10;i++{
numChan <- i
fmt.Println("写入数据:", i)
}
close(numChan)
}()
for {
v, ok := <- numChan // ok-idom模式判断
if !ok {
fmt.Println("管道已关闭,准备退出")
break
}
fmt.Println("v:", v)
}
fmt.Println("结束")
}
单向通道
NumChan := make(chan int, 10) ==> 双向通道,既可以读,也可以写
单向通道:为了明确语义,一般用于函数参数
单向读通道:var numChanRead <- chan int
单向写通道:var numChanWrite chan <- int
示例如下:
package main
import (
"fmt"
"time"
)
func main() {
// 单向读通道:
// var numChanRead <- chan int
// 单向写通道:
// var numChanWrite chan <- int
// 生产者消费者模型
// c:数组+锁 thread1:写 thread2:读
// Go: goroutine + channel
// 1.在主函数中创建一个双向通道 numChan
numChan := make(chan int, 10)
// 2.将numChan 传递给producer,负责生产
// 双向通道可以赋值给同类型的单向通道,单向不能转双向
go producer(numChan)
// 3.将numChan 传递给consumer 负责消费
go consumer(numChan)
time.Sleep(2 * time.Second)
fmt.Println("结束")
}
// producer 生产者 ==》 提供一个只写的通道
func producer(out chan<- int) {
for i := 0; i < 10; i++ {
out <- i
// data := <- out // 写通道不允许有读取操作
fmt.Println("======> 向管道中写入数据:", i)
}
}
// consumer 消费者 ==》 提供一个只读的通道
func consumer(in <- chan int) {
// in <- 1 // 读通道不允许有写入操作
for v := range in {
fmt.Println("从管道中读取数据:", v)
}
}
Select
当程序中有多个channel协同工作:ch1,ch2;
某一个时刻,ch1或者ch2触发了,程序要做相应的处理,
使用select来监听多个通道,当管道被触发时(写入数据,读取数据,关闭管道)。
select语法与switch case很像,但是所有的分支条件都必须是通道io
示例如下:
package main
import (
"fmt"
"time"
)
func main() {
// var ch1,ch2 chan int
ch1 := make(chan int)
ch2 := make(chan int)
// 启动一个go程,负责监听两个channel
go func() {
for {
fmt.Println("监听中。。。。。。。。。。。。。。。。")
select {
case data1 := <-ch1:
fmt.Println("从ch1读取数据成功,data1:", data1)
case data2 := <-ch2:
fmt.Println("===> 从ch2读取数据成功,data2:", data2)
default:
fmt.Println("select default 分支 called")
time.Sleep(time.Second)
}
}
}()
// 启动go程1 写ch1
go func() {
for i := 0; i < 10; i++ {
ch1 <- i
time.Sleep(1 * time.Second / 2)
}
}()
// 启动go程2 写ch2
go func() {
for i := 0; i < 10; i++ {
ch2 <- i
time.Sleep(1 * time.Second)
}
}()
for {
fmt.Println("结束")
time.Sleep(5 * time.Second)
}
}
总结
本篇文章主要介绍Go语言 管道:判断管道关闭、单向通道及多管道协同工作内容和示例。