multierr for Go: Combining and Working with Multiple Errors
\nIn Go, error handling is an explicit and integral part of development. However, a situation often arises where not one, but several errors can occur during the execution of a single operation. For example, during batch file processing, validation of a complex data structure, or execution of parallel tasks. The standard errors package only allows working with one error at a time, which complicates the collection and analysis of all failures that have occurred.
The multierr library from Uber (yes, the same company that created zap and fx) solves this problem elegantly and efficiently. It provides a simple API for combining several independent errors into one composite error. This allows you to preserve the context of all failures without losing information and handle them in one place. Unlike manually creating error slices, multierr offers convenient functions for combining, checking for errors, and iterating over them.
The main philosophy of the library is simplicity and performance. It does not create unnecessary heap allocations if not needed and tries to minimize overhead. multierr is ideal for cases where you need to collect errors from different sources (e.g., from goroutines) and return them as a single result that can be checked for errors using the standard if err != nil.
Installation
\nThe library is installed using the standard go get command. Make sure you have Go version 1.13 or higher installed (for support of errors.Is and errors.As).
go get go.uber.org/multierr\n After executing the command, the library will be added to your go.mod file. It is imported as follows:
import "go.uber.org/multierr"\n\n Quick Start: Minimal Example
\nLet's look at the simplest case: we have two functions that can return an error. We want to execute both and, if at least one of them failed, return a combined error.
\npackage main\n\nimport (\n "errors"\n "fmt"\n "go.uber.org/multierr"\n)\n\nfunc doSomething() error {\n return errors.New("first error")\n}\n\nfunc doAnotherThing() error {\n return errors.New("second error")\n}\n\nfunc main() {\n var err error\n \n // Execute the first operation\n err = multierr.Append(err, doSomething())\n // Execute the second operation\n err = multierr.Append(err, doAnotherThing())\n \n if err != nil {\n fmt.Println("Errors occurred:")\n // Print all errors separated by a newline\n for _, e := range multierr.Errors(err) {\n fmt.Println("-", e)\n }\n }\n}\n In this example, multierr.Append adds a new error to an existing one. If err is nil, the function simply returns the new error. As a result, we get one composite error that can be broken down into parts using multierr.Errors.
Main Functions and Methods
\nThe multierr library provides a small but very powerful set of functions. Let's look at each of them in detail.
1. multierr.Append
\n Signature: func Append(left error, right error) error
Description: This is the main function for combining two errors. If both errors are nil, it returns nil. If one of them is nil, it returns the other. If both are not nil, they are combined into one composite error.
Also in library