README

go-multierror

CircleCI Go Reference GitHub go.mod Go version

go-multierror is a package for Go that provides a mechanism for representing a list of error values as a single error.

This allows a function in Go to return an error that might actually be a list of errors. If the caller knows this, they can unwrap the list and access the errors. If the caller doesn't know, the error formats to a nice human-readable format.

go-multierror is fully compatible with the Go standard library errors package, including the functions As, Is, and Unwrap. This provides a standardized approach for introspecting on error values.

Installation and Docs

Install using go get github.com/hashicorp/go-multierror.

Full documentation is available at https://pkg.go.dev/github.com/hashicorp/go-multierror

Requires go version 1.13 or newer

go-multierror requires go version 1.13 or newer. Go 1.13 introduced error wrapping, which this library takes advantage of.

If you need to use an earlier version of go, you can use the v1.0.0 tag, which doesn't rely on features in go 1.13.

If you see compile errors that look like the below, it's likely that you're on an older version of go:

/go/src/github.com/hashicorp/go-multierror/multierror.go:112:9: undefined: errors.As
/go/src/github.com/hashicorp/go-multierror/multierror.go:117:9: undefined: errors.Is

Usage

go-multierror is easy to use and purposely built to be unobtrusive in existing Go applications/libraries that may not be aware of it.

Building a list of errors

The Append function is used to create a list of errors. This function behaves a lot like the Go built-in append function: it doesn't matter if the first argument is nil, a multierror.Error, or any other error, the function behaves as you would expect.

var result error

if err := step1(); err != nil {
	result = multierror.Append(result, err)
}
if err := step2(); err != nil {
	result = multierror.Append(result, err)
}

return result

Customizing the formatting of the errors

By specifying a custom ErrorFormat, you can customize the format of the Error() string function:

var result *multierror.Error

// ... accumulate errors here, maybe using Append

if result != nil {
	result.ErrorFormat = func([]error) string {
		return "errors!"
	}
}

Accessing the list of errors

multierror.Error implements error so if the caller doesn't know about multierror, it will work just fine. But if you're aware a multierror might be returned, you can use type switches to access the list of errors:

if err := something(); err != nil {
	if merr, ok := err.(*multierror.Error); ok {
		// Use merr.Errors
	}
}

You can also use the standard errors.Unwrap function. This will continue to unwrap into subsequent errors until none exist.

Extracting an error

The standard library errors.As function can be used directly with a multierror to extract a specific error:

// Assume err is a multierror value
err := somefunc()

// We want to know if "err" has a "RichErrorType" in it and extract it.
var errRich RichErrorType
if errors.As(err, &errRich) {
	// It has it, and now errRich is populated.
}

Checking for an exact error value

Some errors are returned as exact errors such as the ErrNotExist error in the os package. You can check if this error is present by using the standard errors.Is function.

// Assume err is a multierror value
err := somefunc()
if errors.Is(err, os.ErrNotExist) {
	// err contains os.ErrNotExist
}

Returning a multierror only if there are errors

If you build a multierror.Error, you can use the ErrorOrNil function to return an error implementation only if there are errors to return:

var result *multierror.Error

// ... accumulate errors here

// Return the `error` only if errors were added to the multierror, otherwise
// return nil since there are no errors.
return result.ErrorOrNil()
Expand ▾ Collapse ▴

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Flatten

func Flatten(err error) error

    Flatten flattens the given error, merging any *Errors together into a single *Error.

    func ListFormatFunc

    func ListFormatFunc(es []error) string

      ListFormatFunc is a basic formatter that outputs the number of errors that occurred along with a bullet point list of the errors.

      func Prefix

      func Prefix(err error, prefix string) error

        Prefix is a helper function that will prefix some text to the given error. If the error is a multierror.Error, then it will be prefixed to each wrapped error.

        This is useful to use when appending multiple multierrors together in order to give better scoping.

        Types

        type Error

        type Error struct {
        	Errors      []error
        	ErrorFormat ErrorFormatFunc
        }

          Error is an error type to track multiple errors. This is used to accumulate errors in cases and return them as a single "error".

          func Append

          func Append(err error, errs ...error) *Error

            Append is a helper function that will append more errors onto an Error in order to create a larger multi-error.

            If err is not a multierror.Error, then it will be turned into one. If any of the errs are multierr.Error, they will be flattened one level into err. Any nil errors within errs will be ignored. If err is nil, a new *Error will be returned.

            func (*Error) Error

            func (e *Error) Error() string

            func (*Error) ErrorOrNil

            func (e *Error) ErrorOrNil() error

              ErrorOrNil returns an error interface if this Error represents a list of errors, or returns nil if the list of errors is empty. This function is useful at the end of accumulation to make sure that the value returned represents the existence of errors.

              func (*Error) GoString

              func (e *Error) GoString() string

              func (Error) Len

              func (err Error) Len() int

                Len implements sort.Interface function for length

                func (Error) Less

                func (err Error) Less(i, j int) bool

                  Less implements sort.Interface function for determining order

                  func (Error) Swap

                  func (err Error) Swap(i, j int)

                    Swap implements sort.Interface function for swapping elements

                    func (*Error) Unwrap

                    func (e *Error) Unwrap() error

                      Unwrap returns an error from Error (or nil if there are no errors). This error returned will further support Unwrap to get the next error, etc. The order will match the order of Errors in the multierror.Error at the time of calling.

                      The resulting error supports errors.As/Is/Unwrap so you can continue to use the stdlib errors package to introspect further.

                      This will perform a shallow copy of the errors slice. Any errors appended to this error after calling Unwrap will not be available until a new Unwrap is called on the multierror.Error.

                      func (*Error) WrappedErrors

                      func (e *Error) WrappedErrors() []error

                        WrappedErrors returns the list of errors that this Error is wrapping. It is an implementation of the errwrap.Wrapper interface so that multierror.Error can be used with that library.

                        This method is not safe to be called concurrently. Unlike accessing the Errors field directly, this function also checks if the multierror is nil to prevent a null-pointer panic. It satisfies the errwrap.Wrapper interface.

                        type ErrorFormatFunc

                        type ErrorFormatFunc func([]error) string

                          ErrorFormatFunc is a function callback that is called by Error to turn the list of errors into a string.

                          type Group

                          type Group struct {
                          	// contains filtered or unexported fields
                          }

                            Group is a collection of goroutines which return errors that need to be coalesced.

                            func (*Group) Go

                            func (g *Group) Go(f func() error)

                              Go calls the given function in a new goroutine.

                              If the function returns an error it is added to the group multierror which is returned by Wait.

                              func (*Group) Wait

                              func (g *Group) Wait() *Error

                                Wait blocks until all function calls from the Go method have returned, then returns the multierror.