goroutine 并发案例
2023-02-01 19:57 糯米粥 阅读(44) 评论(0) 编辑 收藏 举报
1. go select是一种仅能用于channel发送和接收消息的语句,此语句运行期间是阻塞的;当 select中没有case语句的时候,会阻塞当前goroutine
2. select是go在语言层面提供的IO多路复用机制,专门用于检测多个channel是否准备完毕:可读可写
3. select语句中除default外,每个case操作一个channel,要么读要么写
4. select语句中除default外,各case的执行顺序是完全随机的
5. select中如果没有default语句,则会阻塞等待任一case
6. select语句中读操作要判断是否成功读取,关闭的channel也可以读取

package main import ( "fmt" "time" ) type document struct { source string name string address string mobile string } // 采集A数据 func readA() chan document { c := make(chan document) go func() { i := 0 for { //模拟等待3s time.Sleep(3 * time.Second) c <- document{ source: "A", name: fmt.Sprintf("姓名%d", i), //模拟数据 address: fmt.Sprintf("地址%d", i), mobile: fmt.Sprintf("手机号码%d", i), } i++ } }() return c } // 采集B数据 func readB() chan document { c := make(chan document) go func() { i := 0 for { //模拟等待1s,2边的时间不能等待一样 time.Sleep(1 * time.Second) c <- document{ source: "B", name: fmt.Sprintf("姓名%d", i), //模拟数据 address: fmt.Sprintf("地址%d", i), mobile: fmt.Sprintf("手机号码%d", i), } i++ } }() return c } // 分别从每个采集中接收数据,分发到main func receiveInfo(chs ...chan document) chan document { doc := make(chan document) for _, c := range chs { go func(in chan document) { for { doc <- <-in //从c中接收消息,发送给c } }(c) } return doc } // func main() { // ch1 := make(chan<- int, 1) // ch2 := make(chan int, 1) // ch1 <- 9 // select { // case ch1 <- 90: // fmt.Println("ch1 pop one element") // case <-ch2: // fmt.Println("ch2 pop one element") // } // } func main() { //接收数据,模拟入库 a := readA() //创建A b := readB() //创建b receA := receiveInfo(a, b) for { /*fmt.Println(<-c1) fmt.Println(<-c2)*/ //m := <-receA //if m.source == "A" { // time.Sleep(5 * time.Second) // //如果这里逻辑处理比较慢,处理速度大于传来的速度,数据就会丢失 // fmt.Printf("接收A的数据,并入库:%s\n", m) //} else { // fmt.Printf("接收B的数据,并入库:%s\n", m) //} //如果这里逻辑处理比较慢,处理速度大于传来的速度,数据就会丢失,所以先保存数据 var values []document select { case n := <-receA: values = append(values, n) } if len(values) > 0 { m := values[0] //获取第一个 if m.source == "A" { time.Sleep(5 * time.Second) fmt.Printf("接收A的数据,并入库:%+v\n", m) } else { fmt.Printf("接收B的数据,并入库:%+v\n", m) } //删除第一个 values = values[1:] } //select { //case m.source == "A": // fmt.Printf("接收A的数据,并入库:%s\n", m) // case m.source=="B" // fmt.Printf("接收A的数据,并入库:%s\n", m) //} } }
参考:
https://www.cnblogs.com/xingchong/p/15826630.html
https://www.cnblogs.com/juanmaofeifei/p/14436952.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
2015-02-01 unity3d-游戏实战突出重围,整合游戏