group.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. package errors
  2. // ErrorGroup is an interface for multiple errors that are not a chain.
  3. // This happens for example when executing multiple operations in parallel.
  4. type ErrorGroup interface {
  5. Errors() []error
  6. }
  7. // Errors uses the ErrorGroup interface to return a slice of errors.
  8. // If the ErrorGroup interface is not implemented it returns an array containing just the given error.
  9. func Errors(err error) []error {
  10. if eg, ok := err.(ErrorGroup); ok {
  11. return eg.Errors()
  12. }
  13. return []error{err}
  14. }
  15. // WalkDeep does a depth-first traversal of all errors.
  16. // Any ErrorGroup is traversed (after going deep).
  17. // The visitor function can return true to end the traversal early
  18. // In that case, WalkDeep will return true, otherwise false.
  19. func WalkDeep(err error, visitor func(err error) bool) bool {
  20. // Go deep
  21. unErr := err
  22. for unErr != nil {
  23. if done := visitor(unErr); done {
  24. return true
  25. }
  26. unErr = Unwrap(unErr)
  27. }
  28. // Go wide
  29. if group, ok := err.(ErrorGroup); ok {
  30. for _, err := range group.Errors() {
  31. if early := WalkDeep(err, visitor); early {
  32. return true
  33. }
  34. }
  35. }
  36. return false
  37. }