在 `ErrorPool` 中,将错误存储为 `[]error` 而不是扁平化的 `error`
在下面的代码片段中,我们可以看到错误是按顺序加入的:
go
func (p *ErrorPool) addErr(err error) {
if err != nil {
p.mu.Lock()
if p.onlyFirstError {
if p.errs == nil {
p.errs = err
}
} else {
p.errs = multierror.Join(p.errs, err)
}
p.mu.Unlock()
}
}
但是,如果没有递归函数,从 ErrorPool#Wait() 中获取底层错误会非常困难(当前的方法还以不最优的方式存储错误,导致更多的内存使用,但这并不是一个大问题):
go
func unwrapErrors(err error) []error {
if err == nil {
return nil
}
v, ok := err.(interface{ Unwrap() []error })
if !ok {
return []error{err}
}
var errs []error
for _, wErr := range v.Unwrap() {
errs = append(errs, unwrapErrors(wErr)...)
}
return errs
}
如果错误保留为 []error,并且 errors.Join(p.errs) 在 ErrorPool#Wait() 中执行,则从中获取底层错误只需一行代码:
res, err := myPool.Wait()
errs := err.(interface{ Unwrap() []error }).Unwrap()
我不介意为这个工作做出努力,并且应该注意到,它与那些在野中创建了像上面的 unwrapErrors 这样的函数的人是相容的。
内容来源: sourcegraph/conc