var _singlelineSeparator … var _multilinePrefix … var _multilineSeparator … var _multilineIndent … var _bufferPool … type errorGroup … // Errors returns a slice containing zero or more errors that the supplied // error is composed of. If the error is nil, a nil slice is returned. // // err := multierr.Append(r.Close(), w.Close()) // errors := multierr.Errors(err) // // If the error is not composed of other errors, the returned slice contains // just the error that was passed in. // // Callers of this function are free to modify the returned slice. func Errors(err error) []error { … } type multiError … // Errors returns the list of underlying errors. // // This slice MUST NOT be modified. func (merr *multiError) Errors() []error { … } func (merr *multiError) Error() string { … } // Every compares every error in the given err against the given target error // using [errors.Is], and returns true only if every comparison returned true. func Every(err error, target error) bool { … } func (merr *multiError) Format(f fmt.State, c rune) { … } func (merr *multiError) writeSingleline(w io.Writer) { … } func (merr *multiError) writeMultiline(w io.Writer) { … } // Writes s to the writer with the given prefix added before each line after // the first. func writePrefixLine(w io.Writer, prefix []byte, s string) { … } type inspectResult … // Inspects the given slice of errors so that we can efficiently allocate // space for it. func inspect(errors []error) (res inspectResult) { … } // fromSlice converts the given list of errors into a single error. func fromSlice(errors []error) error { … } // Combine combines the passed errors into a single error. // // If zero arguments were passed or if all items are nil, a nil error is // returned. // // Combine(nil, nil) // == nil // // If only a single error was passed, it is returned as-is. // // Combine(err) // == err // // Combine skips over nil arguments so this function may be used to combine // together errors from operations that fail independently of each other. // // multierr.Combine( // reader.Close(), // writer.Close(), // pipe.Close(), // ) // // If any of the passed errors is a multierr error, it will be flattened along // with the other errors. // // multierr.Combine(multierr.Combine(err1, err2), err3) // // is the same as // multierr.Combine(err1, err2, err3) // // The returned error formats into a readable multi-line error message if // formatted with %+v. // // fmt.Sprintf("%+v", multierr.Combine(err1, err2)) func Combine(errors ...error) error { … } // Append appends the given errors together. Either value may be nil. // // This function is a specialization of Combine for the common case where // there are only two errors. // // err = multierr.Append(reader.Close(), writer.Close()) // // The following pattern may also be used to record failure of deferred // operations without losing information about the original error. // // func doSomething(..) (err error) { // f := acquireResource() // defer func() { // err = multierr.Append(err, f.Close()) // }() // // Note that the variable MUST be a named return to append an error to it from // the defer statement. See also [AppendInvoke]. func Append(left error, right error) error { … } // AppendInto appends an error into the destination of an error pointer and // returns whether the error being appended was non-nil. // // var err error // multierr.AppendInto(&err, r.Close()) // multierr.AppendInto(&err, w.Close()) // // The above is equivalent to, // // err := multierr.Append(r.Close(), w.Close()) // // As AppendInto reports whether the provided error was non-nil, it may be // used to build a multierr error in a loop more ergonomically. For example: // // var err error // for line := range lines { // var item Item // if multierr.AppendInto(&err, parse(line, &item)) { // continue // } // items = append(items, item) // } // // Compare this with a version that relies solely on Append: // // var err error // for line := range lines { // var item Item // if parseErr := parse(line, &item); parseErr != nil { // err = multierr.Append(err, parseErr) // continue // } // items = append(items, item) // } func AppendInto(into *error, err error) (errored bool) { … } type Invoker … type Invoke … // Invoke calls the supplied function and returns its result. func (i Invoke) Invoke() error { … } // Close builds an Invoker that closes the provided io.Closer. Use it with // AppendInvoke to close io.Closers and append their results into an error. // // For example, // // func processFile(path string) (err error) { // f, err := os.Open(path) // if err != nil { // return err // } // defer multierr.AppendInvoke(&err, multierr.Close(f)) // return processReader(f) // } // // In this example, multierr.Close will construct the Invoker right away, but // defer the invocation of f.Close until the function returns. // // defer multierr.AppendInvoke(&err, multierr.Close(f)) // // Note that the error you're appending to from the defer statement MUST be a // named return. func Close(closer io.Closer) Invoker { … } // AppendInvoke appends the result of calling the given Invoker into the // provided error pointer. Use it with named returns to safely defer // invocation of fallible operations until a function returns, and capture the // resulting errors. // // func doSomething(...) (err error) { // // ... // f, err := openFile(..) // if err != nil { // return err // } // // // multierr will call f.Close() when this function returns and // // if the operation fails, its append its error into the // // returned error. // defer multierr.AppendInvoke(&err, multierr.Close(f)) // // scanner := bufio.NewScanner(f) // // Similarly, this scheduled scanner.Err to be called and // // inspected when the function returns and append its error // // into the returned error. // defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err)) // // // ... // } // // NOTE: If used with a defer, the error variable MUST be a named return. // // Without defer, AppendInvoke behaves exactly like AppendInto. // // err := // ... // multierr.AppendInvoke(&err, mutltierr.Invoke(foo)) // // // ...is roughly equivalent to... // // err := // ... // multierr.AppendInto(&err, foo()) // // The advantage of the indirection introduced by Invoker is to make it easy // to defer the invocation of a function. Without this indirection, the // invoked function will be evaluated at the time of the defer block rather // than when the function returns. // // // BAD: This is likely not what the caller intended. This will evaluate // // foo() right away and append its result into the error when the // // function returns. // defer multierr.AppendInto(&err, foo()) // // // GOOD: This will defer invocation of foo unutil the function returns. // defer multierr.AppendInvoke(&err, multierr.Invoke(foo)) // // multierr provides a few Invoker implementations out of the box for // convenience. See [Invoker] for more information. func AppendInvoke(into *error, invoker Invoker) { … } // AppendFunc is a shorthand for [AppendInvoke]. // It allows using function or method value directly // without having to wrap it into an [Invoker] interface. // // func doSomething(...) (err error) { // w, err := startWorker(...) // if err != nil { // return err // } // // // multierr will call w.Stop() when this function returns and // // if the operation fails, it appends its error into the // // returned error. // defer multierr.AppendFunc(&err, w.Stop) // } func AppendFunc(into *error, fn func() error) { … }