用互斥锁正确保存多个协程中的第一个错误

编程语言 2026-07-09

我正在编写一个函数,在并行的goroutine中获取学生成绩,并在末尾返回它们的算术平均值。如果至少有一个学生有错误,函数应该返回首次发生的错误。

如何正确处理这个错误?可能会有一些问题。我需要先为错误定义mu.Lock(),并对sum使用defer mu.Unlock()。

func Average(names []string) (int, error) {
    mu := &sync.Mutex{}
    wg := &sync.WaitGroup{}
    sum := 0
    var firstErr error

    for _, name := range names {
        wg.Add(1)
        go func(n string) {
            defer wg.Done()

            elem, err := GetMarks(n)

            mu.Lock()
            defer mu.Unlock()

            if err != nil {
                if firstErr == nil {
                    firstErr = err
                }
                return
            }

            sum += elem

            mu.Unlock()
        }(name)

    }
    wg.Wait()

    if firstErr != nil {
        return 0, firstErr
    }

    if len(names) == 0 {
        return 0, nil
    }

    return sum / len(names), nil
}

解决方案

我会直接使用errgroup,不会把事情搞得过于复杂,也许如果出现任何错误,直接停止并立即返回会更合适。当然,使用通道也可以实现,在这种情况下我个人可以这样做

eg := &errgroup.Group{}
mu := &sync.Mutex{}

var total int
for _, name := range names {
    eg.Go(func() error {
        elem, err := GetMarks(n)
        if err != nil {
            return err
        }

        mu.Lock()
        total += elem
        mu.Unlock()

        return nil
    })
}

if err := eg.Wait(); err != nil {
  return err
}

log.Print(total)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章