Documentation ¶
Overview ¶
Package batcherror provides BatchError, which can be used to compile multiple errors into a single one.
An example of how to use it in your functions:
type worker func() error func runWorksParallel(works []worker) error { errChan := make(chan error, len(works)) var wg sync.WaitGroup wg.Add(len(works)) for _, work := range works { go func(work worker) { defer wg.Done() errChan <- work() }(work) } wg.Wait() var batch batcherror.BatchError for err := range errChan { // nil errors will be auto skipped batch.Add(err) } // If all works succeeded, Compile() returns nil. // If only one work failed, Compile() returns that error directly // instead of wrapping it inside BatchError. return batch.Compile() }
This package is not thread-safe. The same batch should not be operated on different goroutines concurrently.
Example ¶
package main import ( "errors" "fmt" "github.com/fizx/baseplate.go/batcherror" ) func main() { var batch batcherror.BatchError var singleError error = batch.Compile() fmt.Printf("0: %v\n", singleError) err := errors.New("foo") batch.Add(err) singleError = batch.Compile() fmt.Printf("1: %v\n", singleError) batch.Add(nil) singleError = batch.Compile() fmt.Printf("Nil errors are skipped: %v\n", singleError) err = errors.New("bar") batch.Add(err) singleError = batch.Compile() fmt.Printf("2: %v\n", singleError) var newBatch batcherror.BatchError err = errors.New("foobar") newBatch.Add(err) newBatch.Add(batch) fmt.Printf("3: %v\n", newBatch.Compile()) }
Output: 0: <nil> 1: foo Nil errors are skipped: foo 2: batcherror: total 2 error(s) in this batch: foo; bar 3: batcherror: total 3 error(s) in this batch: foobar; foo; bar
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BatchError ¶
type BatchError struct {
// contains filtered or unexported fields
}
BatchError is an error that can contain multiple errors.
The zero value of BatchError is valid (with no errors) and ready to use.
This type is not thread-safe. The same batch should not be operated on different goroutines concurrently.
func (*BatchError) Add ¶
func (be *BatchError) Add(err error)
Add adds an error into the batch.
If the error is also an BatchError, its underlying error(s) will be added instead of the BatchError itself.
Nil error will be skipped.
func (BatchError) As ¶
func (be BatchError) As(v interface{}) bool
As implements helper interface for errors.As.
If v is pointer to either BatchError or *BatchError, *v will be set into this error. Otherwise, As will try errors.As against all errors in this batch, returning the first match.
See Is for the discussion of possiblity of infinite loop.
Example ¶
This example demonstrates how a BatchError can be inspected with errors.As.
package main import ( "context" "errors" "fmt" "os" "github.com/fizx/baseplate.go/batcherror" ) func main() { var batch batcherror.BatchError var target *os.PathError batch.Add(context.Canceled) err := batch.Compile() fmt.Println(errors.As(err, &target)) // false batch.Add(fmt.Errorf("wrapped: %w", &os.PathError{})) err = batch.Compile() fmt.Println(errors.As(err, &target)) // true batch.Add(fmt.Errorf("wrapped: %w", &os.LinkError{})) err = batch.Compile() fmt.Println(errors.As(err, &target)) // true }
Output: false true true
func (BatchError) Compile ¶
func (be BatchError) Compile() error
Compile compiles the batch.
If the batch contains zero errors, Compile returns nil.
If the batch contains exactly one error, that underlying error will be returned.
Otherwise, the batch itself will be returned.
func (BatchError) Error ¶
func (be BatchError) Error() string
func (BatchError) GetErrors ¶
func (be BatchError) GetErrors() []error
GetErrors returns a copy of the underlying error(s).
func (BatchError) Is ¶
func (be BatchError) Is(target error) bool
Is implements helper interface for errors.Is.
It calls errors.Is against all errors in this batch, until a match is found.
If an error in the batch is the BatchError itself, calling its Is (and As) could cause an infinite loop. But there's a special handling in Add function, that if you try to add a BatchError into the batch, we add the underlying errors instead the BatchError itself. As a result it should be impossible to cause infinite loops in Is and As.
Example ¶
This example demonstrates how a BatchError can be inspected with errors.Is.
package main import ( "context" "errors" "fmt" "io" "github.com/fizx/baseplate.go/batcherror" ) func main() { var batch batcherror.BatchError batch.Add(context.Canceled) err := batch.Compile() fmt.Println(errors.Is(err, context.Canceled)) // true fmt.Println(errors.Is(err, io.EOF)) // false batch.Add(fmt.Errorf("wrapped: %w", io.EOF)) err = batch.Compile() fmt.Println(errors.Is(err, context.Canceled)) // true fmt.Println(errors.Is(err, io.EOF)) // true }
Output: true false true true