5/30 go+channel并发模型 分享笔记
Channel 定义
只能使用 make 进行初始化
ch := make(chan int,0)
- 
有缓存的channel和无缓存channel 
- 
channel 数据操作 - 向channel 中添加数据
- ch <- 数据
 
- 读取数据
- 直接读取 接收变量 := <- ch
- 使用 for rangefunc NoCache() { ch := make(chan int, 10) go func(chan int) { for i := 0; i < 10000; i++ { ch <- i } close(ch) }(ch) // for { // data, ok := <-ch // if !ok{ // break // } // fmt.Println(data) // } for v := range ch { fmt.Println(v) } }
- 使用 for select多个channel时使用
 
- 直接读取 
 
- 向channel 中添加数据
- 
注意事项 - 
channel数据必须有进有出 
 all goroutines are asleep - deadlock!func mian(){ ch := make(chan int, 10) go func(chan int) { for i := 0; i < 10000; i++ { ch <- i } // 不添加close会报错 close(ch) }(ch) for { data := <-ch fmt.Println(data) } }
- 
不能重复关闭同一个channel panic: close of closed channelch := make(chan int) close(ch) close(ch) // panic: close of closed channel
- 
不能向已关闭的channel中发送数据,否则报错 panic: send on closed channelfunc NoCache() { ch := make(chan int, 10) go func(chan int) { for i := 0; i < 10000; i++ { ch <- i } close(ch) }(ch) for v := range ch { fmt.Println(v) if v == 9900 { close(ch) } } }
- 
可以从已关闭的channel中读取数据,没有数据时默认返回零值 func ReadCloseChan() { ch := make(chan int) go func() { for i := 0; i < 10; i++ { ch <- i } close(ch) }() for { // ok 判断通道是否关闭 data, ok := <-ch if !ok { fmt.Println(data, ok) break } fmt.Println(data, ok) } }
 
- 
- 
定时器的使用 func Time() { tim := time.NewTimer(2 * time.Second) for { tim.Reset(2 * time.Second) <-tim.C fmt.Println("执行数据") } }
- 
并发模型 - 
一对多 func OneToMore() { ch := make(chan int, 10) // 一对多模型 一个发送者多个接收者 go func(chan int) { for i := 0; i < 10000; i++ { ch <- i } close(ch) }(ch) var wg sync.WaitGroup wg.Add(10) for i := 0; i < 10; i++ { go func(i int, ch chan int) { defer func() { wg.Done() }() for data := range ch { fmt.Printf("worker %d 执行任务 %d \n", i, data) } }(i, ch) } wg.Wait() fmt.Println("执行完毕") }
- 
多对一 func MoreToOne() { // 多个发送者,一个接收者 type Task struct { WorkerId int TaskId int } ch := make(chan Task, 10) stopChan := make(chan struct{}) // 多个发送者 for i := 0; i < 10; i++ { go func(i int, ch chan Task) { for m := 0; m < 100; m++ { ch <- Task{i, m} } // 监听关闭通知 <-stopChan }(i, ch) } // 一个接收者 tim := time.NewTimer(time.Second * 5) for { var out bool = false tim.Reset(5 * time.Second) select { case data := <-ch: fmt.Printf("处理发送端 %d 发送过来的 %d 号任务 \n", data.WorkerId, data.TaskId) case <-tim.C: // 关闭通知 close(stopChan) out = true } if out { break } } fmt.Println("任务完成") }
- 
多对多 func MoreToMore() { // 多个发送者,一个接收者 type Task struct { WorkerId int TaskId int } ch := make(chan Task, 10) stopChan := make(chan struct{}) warChan := make(chan struct{}) // 多个发送者 for i := 0; i < 10; i++ { go func(i int, ch chan Task, war chan struct{}) { var closeSwitch bool = false for m := 0; m < 100; m++ { // 触发关闭机制 if m == 80 { war <- struct{}{} } select { // 监控stopChannel case <-stopChan: closeSwitch = true case ch <- Task{i, m}: } if closeSwitch { break } } }(i, ch, warChan) } // 多个接收者 for i := 0; i < 10; i++ { go func(i int, ch chan Task) { var closeSwitch bool = false for { select { case data := <-ch: fmt.Printf("接收端 %d 处理发送端 %d 发送过来的 %d 号任务 \n", i, data.WorkerId, data.TaskId) case <-stopChan: closeSwitch = true } if closeSwitch { break } } }(i, ch) } // 创建一个监控者监听发送来的关闭信号 go func(ch chan Task) { <-warChan close(stopChan) }(ch) fmt.Println("任务完成") }
 
- 

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号