当前位置: 首页 > news >正文

Go的管道——channel

CSP  -->不要以内存的方式来通信(要上锁),相反,要通过通信来共享内存channel 本身就是一个队列  先进先出channel 是引用类型  可以使用make初始化   make -- map、slice、channel
channel 写满的时候不能写,取空的时候不能取  很容易发生阻塞  很容易产生死锁
每个channel 只能放同一种类型
使用channel 收发操作都是在不同的goroutinuechannel无缓冲通道有缓冲通道
无缓冲通道
package mainimport ("fmt""time"
)func main() {//无缓冲通道 -->每次只能取一个ch1 := make(chan int)go senddata(ch1)time.Sleep(2 * time.Second)data := <-ch1fmt.Println("拿到通道数据:", data)data2 := <-ch1fmt.Println("拿到通道数据:", data2)//支持不同协程之间的通信// ch1 <- 3// data3 := <-ch1 //不行,会报错// fmt.Println("拿到通道数据:", data3)time.Sleep(2 * time.Second)
}func senddata(ch chan int) {ch <- 1fmt.Println("往通道里存放数据1")ch <- 2fmt.Println("往通道里存放数据2")
}
利用无缓冲通道 做协程的控制
package mainimport ("fmt""time"
)//利用无缓冲通道 做协程的控制
//主协程退出  子协程也会跟着退出。利用通道取控制主协程等待子协程执行完成再退出type signal struct{}func senddata(ch chan int) {fmt.Println("this is senddata...")time.Sleep(2 * time.Second)ch <- 1//子协程执行完了,就往通道里面放数据
}func main() {fmt.Println("this is main")ch1 := make(chan int)go senddata(ch1)fmt.Println("等待子协程执行完毕")<-ch1//从通道里拿到数据,才能继续执行,不然就处于阻塞状态fmt.Println("end...")
}
使用空结构体,更节省空间
package mainimport ("fmt""time"
)
//最好使用空结构体  模拟信号发生type signal struct{}func senddata(ch chan signal) {fmt.Println("this is senddata...")time.Sleep(2 * time.Second)ch <- signal{} //子协程执行完了,就往通道里面放数据
}func main() {fmt.Println("this is main")ch1 := make(chan signal)go senddata(ch1)fmt.Println("等待子协程执行完毕")<-ch1 //从通道里拿到数据,才能继续执行,不然就处于阻塞状态fmt.Println("end...")
}
通道的关闭——消费者不会因为没有数据产生死锁
package mainimport ("fmt""time"
)// 通道的关闭  生产者发送完毕数据,关闭通道。消费者就不会因为没有数据产生死锁
func senddata(ch chan string) {defer fmt.Println("数据发送完毕")for i := 0; i < 3; i++ {ch <- fmt.Sprintf("发送数据:%d", i)}//defer fmt.Println("数据发送完毕")defer close(ch) //关闭通道,拿取方判断通道是否关闭,避免产生死锁
}func main() {ch1 := make(chan string)go senddata(ch1)//方式一  判断通道是否关闭for {data := <-ch1//如果通道关闭,读取的就是数据类型的默认值if data == "" {break}fmt.Println("拿到的数据:", data)}//方式二for {data, ok := <-ch1//如果ok为false  表示通道关闭if !ok {break}fmt.Println("from channel:", data)}//方式三   range   --> string slice  map  channel//range 会自动判断通道是否关闭for value := range ch1 {fmt.Println("from channel:", value)}
}
有缓冲通道
package mainimport ("fmt""time"
)// 有缓冲通道
func main() {ch1 := make(chan string, 6)go senddata(ch1)time.Sleep(2 * time.Second)for data := range ch1 {fmt.Println("读取通道数据:", data)}
}func senddata(ch chan string) {for i := 0; i < 10; i++ {ch <- fmt.Sprintf("data: %d", i)fmt.Println("往通道里放数据:", i)}defer close(ch)
}
监听通道
//select  监听通道
/*
select 同时监听多个通道操作,实现非阻塞通信和多路复用,实现高效的并发处理
select 语句监听多个通道操作,并且执行第一个准备好的操作,如果多个同时准备好,随机挑选一个执行如果没有通道准备好,select语句一直阻塞,直到至少有一个通道操作准备好
*/package mainimport ("fmt""time"
)func main() {ch1 := make(chan int)ch2 := make(chan int)ch3 := make(chan int)go func() {time.Sleep(10 * time.Second)ch1 <- 1}()go func() {time.Sleep(1 * time.Second)ch2 <- 2}()go func() {time.Sleep(3 * time.Second)ch3 <- 3}()for i := 0; i < 3; i++ {select {case msg := <-ch1:fmt.Println("接收到数据from ch1:", msg)case msg := <-ch2:fmt.Println("接收到数据from ch2:", msg)case msg := <-ch3:fmt.Println("接收到数据from ch3:", msg)case <-time.After(1 * time.Second):fmt.Println("设置超时时间,timeout!")// default://  fmt.Println("没有消息准备好!")}}
}
http://www.xdnf.cn/news/1194067.html

相关文章:

  • 大话数据结构之 < 栈>(C语言)
  • InfluxDB Flux 查询协议实战应用(二)
  • Voxtral Mini:语音转文本工具,支持超长音频,多国语音
  • 机器学习对中特估股票关键特征选取的应用与研究
  • pose调研
  • Ubuntu 18.04安装Fast-Lio2教程
  • 第10篇:实战验收篇
  • 【HTML】<script>元素中的 defer 和 async 属性详解
  • Flutter 提取图像主色调 ColorScheme.fromImageProvider
  • 摘录-打造第二大脑
  • Chessboard and Queens
  • 磁悬浮轴承(AMB)系统中引入转速频率陷波器失稳分析
  • MySQL 中 VARCHAR(50) 和 VARCHAR(500) 的区别
  • docker 从主机复制文件到容器外进行编辑
  • Pspice仿真电路:(三十四)如何使用Pspcie进行仿真
  • 定义域第一题
  • 速通python加密之SHA加密
  • SpringBoot总结
  • 广东省省考备考(第五十七天7.26)——数量、言语(强化训练)
  • 如何做数据增强?
  • 大模型面试回答,介绍项目
  • 高性能网络DPDK、RDMA、XDP初探
  • URL与URI:互联网世界的“门牌号“与“身份证“
  • 网络编程2(应用层协议,传输层协议)
  • 「iOS」————继承链与对象的结构
  • SWC 深入全面讲解
  • 口腔助手|口腔挂号预约小程序|基于微信小程序的口腔门诊预约系统的设计与实现(源码+数据库+文档)
  • GitHub的免费账户的存储空间有多少?
  • 基于深度学习的图像分类:使用Capsule Networks实现高效分类
  • 网安-中间件-Redis未授权访问漏洞