Documentation
¶
Overview ¶
Package errortree provides multiple-error matching considering the tree structure of errors in Go1.20 and later.
This package uses generics to keep the type info from the caller, and returns the search result with an arbitrary concrete type.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExactlyIs ¶ added in v0.1.0
ExactlyIs reports whether all branches in the err's tree matches the target.
The tree consists of err itself, followed by the errors obtained by repeatedly calling Unwrap. When err wraps multiple errors, Is examines err followed by a depth-first traversal of its children.
For example, ExactlyIs(err, target) will return true on the following tree because all branches match target when viewed from the root.
err
├── target
├── wrapErr
│ └── multiErr
│ ├── target
│ └── target
└── multiErr
├── wrapErr
│ └── target
└── target
An error is considered to match a target if it is equal to that target or if it implements a method Is(error) bool such that Is(target) returns true.
Example ¶
package main
import (
"errors"
"fmt"
"github.com/convto/errortree"
)
type wrapErr struct {
err error
}
func (e wrapErr) Error() string { return "wrapErr" }
func (e wrapErr) Unwrap() error { return e.err }
type multiErr []error
func (m multiErr) Error() string { return "multiError" }
func (m multiErr) Unwrap() []error { return []error(m) }
func main() {
erra := errors.New("error A")
err := multiErr{
wrapErr{
multiErr{
erra,
erra,
},
},
wrapErr{erra},
multiErr{
erra,
erra,
errors.New("wrong error"),
},
}
result := errortree.ExactlyIs(err, erra)
fmt.Println(result)
}
Output: false
func Scan ¶
Scan finds all matches to target in err's tree, always traverses all trees even if target is found during the search, if no matches are found, it returns nil.
For example, execute Scan(err, target) on the following tree
err
├── targetA(assignable to `target`)
├── wrapErr
│ └── multiErr
│ ├── targetB(assignable to `target`)
│ └── targetC(assignable to `target`)
└── multiErr
├── wrapErr
│ └── targetD(assignable to `target`)
└── targetE(assignable to `target`)
It returns `[]target{targetA, targetB, targetC, targetD, targetE}`.
The tree consists of err itself, followed by the errors obtained by repeatedly calling Unwrap. When err wraps multiple errors, Scan examines err followed by a depth-first traversal of its children.
An error matches target if the err's concrete value is assignable to the value pointed to by target.
Scan panics if target is not implements error, or is not any interface type.
Note target parameter accepts an interface, so setting `interface{}` or `any` to target will match all nodes!
Example ¶
package main
import (
"errors"
"fmt"
"io/fs"
"github.com/convto/errortree"
)
type wrapErr struct {
err error
}
func (e wrapErr) Error() string { return "wrapErr" }
func (e wrapErr) Unwrap() error { return e.err }
type multiErr []error
func (m multiErr) Error() string { return "multiError" }
func (m multiErr) Unwrap() []error { return []error(m) }
func main() {
err := multiErr{
multiErr{
errors.New("error"),
&fs.PathError{Op: "poser A"},
},
wrapErr{&fs.PathError{Op: "poser B"}},
multiErr{
errors.New("error"),
errors.New("error"),
wrapErr{&fs.PathError{Op: "poser C"}},
},
}
var p *fs.PathError
matched := errortree.Scan(err, p)
for _, v := range matched {
fmt.Printf("%s\n", v.Op)
}
}
Output: poser A poser B poser C
Types ¶
This section is empty.