• 大漠胡萝卜
    2020-11-23
    看了这篇文章还是收获巨大,以前不知道,也没用用过。 首先是,ErrGroup, 官方的实现,bilibili/errgroup,neilotoole/errgroup,facebookgo/errgroup 其它实用的 Group 并发原语SizedGroup/ErrSizedGroup gollback各种实现,以前在nodejs中经常使用,没想到golang也有实现。 类似的还有Hunch实现。 另外,如果针对定时器比较多的情况,可以使用 schedgroup

    作者回复: ������������

    
    5
  • mbc
    2020-11-28
    老师,这种和用普通的go协程或者channel去完成一组任务的编写有啥不一样吗?好处是啥

    作者回复: 这一组并发原语只是提供了便利的方法,底层还是用gotoutinr和channel实现的

    共 2 条评论
    2
  • 东泽
    2021-12-10
    文章中多次出现的“让子任务中断执行”,这里的语义是中断子goroutine的执行还是在子goroutine中用类似select <-ctx.Done()的方式在执行任务前判断任务是否应该进行。

    作者回复: M第二种

    
    1
  • moooofly
    2020-11-24
    ```go ... for i := 0; i < total; i++ { // 并发一万个goroutine执行子任务,理论上这些子任务都会加入到Group的待处理列表中 go func() { g.Go(func(ctx context.Context) error { atomic.AddInt64(&count, 1) return nil }) }() } ... ``` 这个地方有点不理解,g.Go() 不就是创建了子 goroutine 了么,为啥这里还要使用 go func() {...} ;我看文章中其他类似地方都没有这么用,只有这里是这样~

    作者回复: 模拟一万个goroutine并发调用g.Go

    共 2 条评论
    1
  • 破障
    2023-04-27 来自广东
    我们应该担心【更进一步,返回所有子任务的错误】这一节: func main() { var g errgroup.Group var result = make([]error, 3) // 启动第一个子任务,它执行成功 g.Go(func() error { time.Sleep(5 * time.Second) fmt.Println("exec #1") result[0] = nil // 保存成功或者失败的结果 return nil }) .... } 这段代码多个 goroutine 写同一个 slice 导致 panic 吗?

    作者回复: 不会

    
    
  • 愤怒的小猥琐
    2022-06-13 来自北京
    errorgroup 49-55 行 为什么要用 go func(){} 去执行 g.Wait() 和 close(ch) 呢,按理说不是应该堵塞等待完成吗?

    作者回复: 嗯,是的。

    
    
  • 秋晨
    2021-06-15
    任务执行流水线 Pipeline 的例子第44行,如果处理失败,返回err,当前的goroutine是否会退出呢,如果会退出的话,开启的goroutine数量少于待处理的数据量的话,会不会出现待处理的数据无goroutine处理

    作者回复: 不会。我建议你遇到此类问题跟进去看一下Go方法的实现就清楚了

    
    
  • 皮卡丘
    2020-11-20
    cancel,失败的子任务可以 cancel 所有正在执行任务,这句话是不是有点绝对,ctx只是传递信号,如果cancel时,还有子任务的gouroutine没有调度或者内部还没有运行到监听信号才会被cancel掉

    作者回复: 所以说是“可以”������,这依赖子goroutine自己想不想cancel

    
    
  • 老王
    2020-12-16
    使用 errgroup 保存多个错误的代码,运行会报 data race 吧
    共 1 条评论
    4
  • 伟伟
    2020-11-26
    package main import ( "context" "fmt" "time" "golang.org/x/sync/errgroup" ) type Data struct { } func getData() (*Data, error) { time.Sleep(3 * time.Second) return &Data{}, nil } func main() { c, cancel := context.WithCancel(context.Background()) defer cancel() g, ctx := errgroup.WithContext(c) datas := make(chan *Data, 10) g.Go(func() error { // 业务逻辑 data, err := getData() if err != nil { return err } select { case <-ctx.Done(): return ctx.Err() default: } datas <- data return nil }) go func() { time.Sleep(1 * time.Second) cancel() }() err := g.Wait() if err == nil { fmt.Println("success") return } fmt.Println("fail", err) } 这里理解的是取消做在业务相关层
    展开
    
    3