常见模式之一:阻塞/屏障模式
定义
顾名思义,就是阻塞等待所有goroutine,直到所有goroutine完成,聚合所有结果
使用场景
-
多个网络请求,聚合结果
-
大任务拆分成多个子任务,聚合结果
示例
package main
import (
"fmt"
"time"
)
func task1(n int, res chan int) {
time.Sleep(time.Millisecond * 30)
res <- n * n
}
func task2(n int, res chan int) {
time.Sleep(time.Millisecond * 10)
res <- n + n
}
func task3(n int, res chan int) {
time.Sleep(time.Millisecond * 20)
res <- n / n
}
func main() {
res := make(chan int, 3)
defer close(res)
go task1(2, res)
go task2(3, res)
go task3(4, res)
var resArr []int
for i := 0; i < 3; i++ {
resArr = append(resArr, <-res)
}
fmt.Println(resArr)
}
打印结果:
[6 1 4]
特殊使用
当我们并发请求,但是聚合结果时,需要顺序给出, 如上例,我们打印想要按照task1,task2,task3 依次给出
可以结合slice 和 和结果收集结构体 改写如下
package main
import (
"fmt"
"time"
)
func task1(n int, res chan ResultMap) {
time.Sleep(time.Millisecond * 30)
res <- ResultMap{
Key: "task1",
Res: n * n,
}
}
func task2(n int, res chan ResultMap) {
time.Sleep(time.Millisecond * 10)
res <- ResultMap{
Key: "task2",
Res: n + n,
}
}
func task3(n int, res chan ResultMap) {
time.Sleep(time.Millisecond * 20)
res <- ResultMap{
Key: "task3",
Res: n / n,
}
}
type ResultMap struct {
Key string
Res int
}
func main() {
taskList := []string{"task1", "task2", "task3"}
res := make(chan ResultMap, 3)
defer close(res)
go task1(2, res)
go task2(3, res)
go task3(4, res)
var resArr []int
l := len(taskList)
collectMap := make(map[string]int)
for i := 0; i < l; i++ {
tmp := <-res
collectMap[tmp.Key] = tmp.Res
}
for _, vv := range taskList {
resArr = append(resArr, collectMap[vv])
}
fmt.Println(resArr)
}
如果有更好的顺序收集结果方式,欢迎评论区指正