持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
🎐 放在前面说的话
大家好,我是沥沥樱 👧🏻
本科在读,此为日常捣鼓.
如有不对,请多指教,也欢迎大家来跟我讨论鸭 👏👏👏
还有还有还有很重要的,麻烦大可爱们动动小手,给沥沥樱点颗心心♥,沥沥樱需要鼓励嗷呜~
今天我们要用channel优雅地收集多协程运行结果
Let’s get it!
channel的使用场景
channel主要用在数据流动的地方:
- 消息传递、消息过滤
- 信号广播
- 事件订阅与广播
- 请求、响应转发
- 任务分发
- 结果汇总
- 并发控制
- 同步与异步
- ...
下面我们来讲一下利用channel对多协程进行结果汇总
结果汇总
Go协程通常使用channel(通道)通讯从而协调/同步它们的工作。合理利用Go协程和channel能帮助我们大大提升程序的性能。比如,有些时候我们需要同时执行多个协程,然后再根据其结果再进行处理,这时候收集多个协程的值就非常关键。
基础代码
单个协程执行完毕,直接打印
func main() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ { // 开启5个协程
wg.Add(1)
go func(index int) {
fmt.Println(index)
}(i)
}
wg.Done()
time.Sleep(time.Second)
}
因为协程执行是无序的,所以打印出来的并不一定时顺序的
打印:
4
1
0
3
2
channel汇总
在上面的代码基础上,使用channel对协程结果进行汇总并输出
func main() {
var wg sync.WaitGroup
ch := make(chan int)
for i := 0; i < 5; i++ { // 开启5个协程
wg.Add(1)
go func(index int) {
defer wg.Done()
ch <- index // 将写成数据写入channel
}(i)
}
// 等待所有goroutine执行完之后再关闭通道 defer方式关闭
go func() {
defer close(ch)
wg.Wait()
}()
time.Sleep(time.Second)
for msg := range ch {
fmt.Println(msg) // 遍历channel
}
}
打印: 0 1 4 2 3
解决在取数据时不关注 channel 里面的协程是否处理完了的原理,再开一个协程跑 wg.Wait,因为它能确保被挂在 wg 里面的所有协程都执行完毕了才会被执行,有点想监工的感觉。
🎉 放在后面说的话
以上简单举了一个channel收集多协程运行结果的栗子