← All writing
TIL: errors.Join collects multiple errors in Go
Today I wanted to try a few fallbacks and, if they all failed, return one error
that explains every attempt. Since Go 1.20 there’s a clean way to do that:
errors.Join.
var errs []error
for _, cred := range candidates {
if err := tryClone(repo, cred); err != nil {
errs = append(errs, err)
continue
}
return nil // one worked
}
return fmt.Errorf("all clone attempts failed: %w", errors.Join(errs...))
Two things I didn’t expect:
errors.Join(nil, nil)returnsnil. Nils are skipped, so you can append freely without guarding.errors.Is/errors.Assee through it. The joined error wraps every child, soerrors.Is(err, context.DeadlineExceeded)still matches even if the deadline error was just one of several.
The default Error() string prints each error on its own line, which is exactly
what you want in a log. Small thing, but it replaced a pile of manual
string-joining I’d been copy-pasting for years.