用互斥锁正确保存多个协程中的第一个错误
我正在编写一个函数,在并行的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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。