batcherror

package
v0.0.0-...-bde19ca Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2020 License: BSD-3-Clause Imports: 3 Imported by: 0

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) Clear

func (be *BatchError) Clear()

Clear clears the batch.

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL