目的
- 通用的多函数同时执行模板,所有函数执行结果均不为error时表示执行成功
- 带上上下文Context做超时处理
代码
func FuncsParallelRunningWithContext(functions []func() error, ctx context.Context) (err error) {
var waitGroup sync.WaitGroup
errChan := make(chan error, len(functions))
for _, f := range functions {
waitGroup.Add(1)
go func(f func() error) {
defer waitGroup.Done()
err := f()
if err != nil {
errChan <- err
}
}(f)
}
go func() {
waitGroup.Wait()
errChan <- nil
}()
select {
case err = <-errChan:
return err
case <-ctx.Done():
return fmt.Errorf("time out")
}
}
测试
func test1() error {
fmt.Println("执行第一个")
time.Sleep(time.Second * 1)
fmt.Println("第一个执行完毕")
return nil
}
func test2() error {
fmt.Println("执行第二个")
time.Sleep(time.Second * 2)
fmt.Println("第二个执行失败")
return fmt.Errorf("第二个执行失败")
}
func test3() error {
fmt.Println("执行第三个")
time.Sleep(time.Second * 3)
fmt.Println("第三个执行完毕")
return nil
}
func main() {
funcs := []func() error{test1, test2, test3}
ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(1*time.Second))
fmt.Println(util.FuncsParallelRunningWithContext(funcs, ctx))
}
扩展
- 当前版本在超时之后,各子协程仍然运行,这个需要各函数支持传入context进行判断操作
- 当前版本不具体考虑到每个函数的执行结果,只要有一个失败就报失败,如果需要每个函数的执行结果的话,可以创建相同长度的结果列表,在遍历执行协程时传入下标,进行函数运行和结果赋值