常见模式之一:阻塞/屏障模式
定义
顾名思义,就是阻塞等待所有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 []intfor 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 stringRes 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 []intl := len(taskList)collectMap := make(map[string]int)for i := 0; i < l; i++ {tmp := <-rescollectMap[tmp.Key] = tmp.Res}for _, vv := range taskList {resArr = append(resArr, collectMap[vv])}fmt.Println(resArr)
}
如果有更好的顺序收集结果方式,欢迎评论区指正