https://github.com/lestrrat-go/merror
Error representing multiple errors
https://github.com/lestrrat-go/merror
Last synced: 8 months ago
JSON representation
Error representing multiple errors
- Host: GitHub
- URL: https://github.com/lestrrat-go/merror
- Owner: lestrrat-go
- License: mit
- Created: 2022-05-16T01:28:33.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2022-06-03T03:02:09.000Z (over 3 years ago)
- Last Synced: 2023-08-07T14:24:00.470Z (over 2 years ago)
- Language: Go
- Size: 21.5 KB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
merrors
=======
Simple multi-error `error` type for Go.
tl;dr:
* Sometimes you want multiple errors to be bundled into a single error.
* Whereas other libraries directly act on the error object, this package uses a builder to create errors. This significanly reduces the complexity of the error object itself.
* This unique design allows for graceful handling of collecting errors from multiple goroutines, and also to properly return a `nil` error when there are no errors.
# DESCRIPTION
Simple usage:
```go
package merror_test
import (
"fmt"
"github.com/lestrra-go/merror"
)
func ExampleMerror() {
err1 := fmt.Errorf(`first error`)
err2 := fmt.Errorf(`second error`)
err3 := fmt.Errorf(`third error`)
err := merror.NewBuilder().
Error(err1).
Error(err2).
Error(err3).
Build()
for _, suberr := range err.Errors() {
fmt.Printf("%s\n", suberr.Error())
}
// OUTPUT:
// first error
// second error
// third error
}
```
source: [merror_example_test.go](https://github.com/lestrrat-go/merror/blob/main/merror_example_test.go)
Use with multiple goroutines:
```go
package merror_test
import (
"context"
"fmt"
"sort"
"sync"
"github.com/lestrra-go/merror"
)
func ExampleMerror_MultipleGoroutines() {
b := merror.NewBuilder()
ctx := b.NewContext(context.Background())
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
i := i
go func(ctx context.Context) (err error) {
defer wg.Done()
defer merror.AddToContext(ctx, &err)
return fmt.Errorf(`%d`, i)
}(ctx)
}
wg.Wait()
// note: in order to make the the output deterministic,
// we're having to sort the errors
errs := b.Build().Errors()
sort.Slice(errs, func(i, j int) bool {
return errs[i].Error() < errs[j].Error()
})
for _, err := range errs {
fmt.Printf("%s\n", err)
}
// OUTPUT:
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
}
```
source: [merror_goroutine_example_test.go](https://github.com/lestrrat-go/merror/blob/main/merror_goroutine_example_test.go)
Also, this package works great when you actually want to detect if there were any errors at all. When the `Builder` is not passed any errors before `Build()` is called, then the `Build()` method returns nil, so you can actuall check if there were any errors in an idiomatic way.
```go
package merror_test
import (
"context"
"fmt"
"sync"
"github.com/lestrra-go/merror"
)
func ExampleMerror_NoErrors() {
b := merror.NewBuilder()
ctx := b.NewContext(context.Background())
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
go func(ctx context.Context) (err error) {
defer merror.AddToContext(ctx, &err)
defer wg.Done()
// No errors!
return
}(ctx)
}
wg.Wait()
if errs := b.Build(); errs != nil {
fmt.Printf("%s\n", errs)
}
// OUTPUT:
}
```
source: [merror_noerror_example_test.go](https://github.com/lestrrat-go/merror/blob/main/merror_noerror_example_test.go)