traverse.go

v0.2.0
Doc Versions Source
1
package culpa
2
3
// Walk calls fn for each error in the tree (pre-order, depth-first).
4
// Handles both single-unwrap and multi-unwrap (joined) errors.
5
// Stops early if fn returns false.
6
func Walk(err error, fn func(err error) bool) {
7
	walkTree(err, fn)
8
}
9
10
// Find returns the first error in the tree for which fn returns true
11
// (pre-order, depth-first). Returns nil if no error matches.
12
func Find(err error, fn func(err error) bool) error {
13
	var found error
14
	walkTree(err, func(e error) bool {
15
		if fn(e) {
16
			found = e
17
			return false
18
		}
19
		return true
20
	})
21
	return found
22
}
23
24
// Cause returns the innermost (root-cause) error by following the first
25
// unwrap path. For joined errors, it follows the first child.
26
func Cause(err error) error {
27
	for {
28
		switch u := err.(type) {
29
		case interface{ Unwrap() error }:
30
			next := u.Unwrap()
31
			if next == nil {
32
				return err
33
			}
34
			err = next
35
		case interface{ Unwrap() []error }:
36
			errs := u.Unwrap()
37
			if len(errs) == 0 {
38
				return err
39
			}
40
			err = errs[0]
41
		default:
42
			return err
43
		}
44
	}
45
}
46

Source Files