SoFunction
Updated on 2025-05-23

Golang errors bag quick to get started

In Golang, the errors package is a standard library for handling errors. The errors package provides relatively simple functions and is very convenient to use.

Next, let’s explain in detail the variables, types and functions provided by the errors package.

1. Variables

The errors package only defines a global variable ErrUnsupported.

var ErrUnsupported = New("unsupported operation")

ErrUnsupported means that the requested operation cannot be performed because it is not supported. For example, when the file system used does not support hard links.

Functions and methods should not return this error, but should return an error containing the appropriate context, satisfying:

(err, )

Either wrap ErrUnsupported directly or implement an Is method.

Functions and methods should indicate under which cases an error containing ErrUnsupported will be returned.

2. Type

Error is a built-in interface type. Any type implements the error interface as long as the Error() string method is implemented, which means that instances of this type can be processed as an error.

// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
    Error() string
}

3. Function

3.1 New

Used to create a new error object. It receives a string as an error message and returns an error object.

func New(text string) error

We can see its specific implementation:

// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.
func New(text string) error {
    return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
    s string
}

func (e *errorString) Error() string {
    return 
}

As you can see, New returns the specific type *errorString that implements the error interface.

3.2 Is

Introduction

Functions are a core tool for error handling, which is used to check whether there is a specific error instance in the error chain.

It is one of the error handling enhancements introduced in Go version 1.13, and together with and provide a more flexible error handling mechanism.

Function signature

func Is(err, target error) bool
  • err: Error to check.
  • target: The error we want to confirm.
  • Return value: Return true if any error in the error chain is the same as the target error.

Core functions

  • Recursive unpacking error chains will be unpacked layer by layer through the Unwrap() or Unwrap() []error method to check whether each layer of error matches the target.
  • Value equality check checks whether the wrong "value" is equal to target. The == operator is used by default, but if the error type implements the Is(error) bool method, the method is called first for judgment (using custom equality logic).
  • Support for custom error matching logic If a custom error type requires the definition of special equality rules (such as comparing structure fields instead of pointer addresses), the Is(error) bool method can be implemented.

Sample code

package main

import (
    "errors"
    "fmt"
)

var ErrNotFound = ("not found")

func main() {
    err := ("context: %w", ErrNotFound)
    if (err, ErrNotFound) {
        ("The error chain contains ErrNotFound")
    }

    errNotFoundNew := ("not found")
    ((errNotFoundNew, ErrNotFound)) // false
}

Run output:

ErrNotFound is included in the error chain
false

Because err is wrapped based on ErrNotFound, Is judges to return true.

Because errNotFoundNew is a new error, although the error content is the same as ErrNotFound, the two are two independent error objects, so Is judged to return false.

Use scenarios

  • Check for predefined errors such as determining whether the error is or:
if (err, ) {
    // Process file end logic}
  • Custom Error Match Custom Is method when you need to match according to some of the fields of the error (rather than pointer address):
type ValidationError struct { Field string }
func (e *ValidationError) Is(target error) bool {
    t, ok := target.(*ValidationError)
    return ok &&  == 
}
  • Handle multi-layer error chains automatically traverse package errors (such as error chains generated by +%w):
err := ("layer2: %w", ("layer1: %w", originalErr))
if (err, originalErr) { // Check the lowest error directly    // Match successfully}

Differences from the == operator:

  • Default Behavior: If the Is method is not implemented by the error type, the default == comparison of the error value and target. But for pointer type errors (such as &MyError{}), == compares the pointer address rather than the value content.
  • Custom logic: By implementing the Is method, you can control wrong matching logic (such as comparing structure fields).

Things to note

  • Preferential implementation of Is methods: If custom errors require support for value matching (rather than pointer matching), the Is method must be implemented.

  • target can be nil: if target is nil, return true only if err is also nil.

  • Recursive unpacking can result in slight performance overhead when the performance error chain is long, but is usually negligible.

summary

It is one of the cornerstones of Go error handling, which provides a safe and unified way to check the existence of specific errors by recursively unpacking error chains. Combining the following practices can maximize its effectiveness:

  • Implement the Is method for custom errors that require value matching.
  • Preferential use rather than == to directly compare errors (ensure compatibility with error chains).
  • With Division of Labor: Is is used for value matching, and As is used for type extraction.

3.3 As

Introduction

Functions in Golang are an important tool for error handling. They provide a type-safe way to check whether there is a specific type of error in the error tree and extract error instances of that type.

It is one of the error handling enhancements introduced in Go 1.13, and together with and constitute a more flexible error handling mechanism.

Function signature

func As(err error, target any) bool
  • err: The error tree to be checked.
  • target: A pointer to the target type, used to store the result.
  • Return value: Return true if the specified type exists in the error tree, and the target parameter is set to the corresponding error value.

Core functions

The error tree will be recursively traversed (unwrap errors through the Unwrap() or Unwrap() []error method) to check for errors that match the target type. If found, it assigns the matching error value to the target and returns true.

If the specific value of the error can be assigned to the value pointed to by the target, or if the error has a method As(any) bool that makes As(target) return true, the error matches the target. In the latter case, the As method is responsible for setting the error value to the target.

Differences from:

  • (err, target): Check whether there is an error in the error tree with a value equal to target (value comparison).
  • (err, &target): Check whether there are errors in the error tree that matches the target (type assertion).

Sample code

package main

import (
    "errors"
    "fmt"
)

// Custom error typetype MyError struct {
    Code    int
    Message string
}

func (e *MyError) Error() string {
    return ("code: %d, msg: %s", , )
}

func main() {
    err := &MyError{Code: 404, Message: "Not Found"}
    wrappedErr := ("wrapper: %w", err) // Package error
    var myErr *MyError
    if (wrappedErr, &myErr) {
        ("Found MyError:", , )
        // Output: Found MyError: 404 Not Found    }
}

In this example:

  • Custom error type MyError implements the error interface.
  • The error tree is formed by wrapping the original error with %w.
  • Check the packaged error tree, find an error instance of type MyError, and assign it to myErr.

Use scenarios

  • Extract detailed information of a specific error type. When the error type contains additional fields (such as error codes, context information), this information can be extracted by.

  • Handle error types in the standard library, For example, check if an error is of type to get detailed information about the file path:

var pathErr *
if (err, &pathErr) {
    ("Failed at path:", )
}
  • Multi-level error unpacking does not require manual call to Unwrap() to traverse the error chain, and nested errors will be automatically handled.

Things to note

  • target must be a pointer target must be a pointer to an interface or a specific type. For example:
var target *MyError        // Correct (specific type pointer)var target error = &MyError{} // Correct (interface type pointer)
  • The type that must match the target needs to be exactly the same as the specific type of an error in the error chain (or interface type).

  • Performance If the error tree is very long, it may require traversing the entire tree, but the performance impact in actual scenarios is usually negligible.

summary

Is the best practice for type assertions in Go error handling, which simplifies the operation of extracting specific types of errors from error chains. Combined with error wrapping (+%w), clear and maintainable error handling logic can be constructed.

3.4 Unwrap

Introduction

It is an error handling function introduced in Go 1.13 to obtain the original error of the wrapped error. It is the core part of the error chain support in Go error handling mechanism.

Function signature

func Unwrap(err error) error
  • Unpacking error: If err is implementedUnwrap() errormethod, the result of the method is returned.
  • When unwrapped: If the error does not support unpacking or is already an underlying error, return nil.
  • Simple and straightforward: Only unpack one layer, and will not recursively unpack the entire error chain.

Core functions

  • Unpacking error chain is used to get from package errors (such as viaand%wThe next layer of error is extracted from the generated error.
  • Supports custom error types. If the custom error type is implementedUnwrap() errormethod,It can be called automatically to unpack the error.

Example of usage

err := ("wrapper: %w", )

unwrapped := (err)
(unwrapped == ) // Output: true(unwrapped)          // Output: EOF Usually with  of %w Use verbs in conjunction:
func process() error {
    if err := step1(); err != nil {
        return ("step1 failed: %w", err)
    }
    // ...
}

err := process()
if (err) != nil {
    // Handle original error}
  • Standard interface: Unwrap() error method required to implement the Unwrap() error method
  • Non-recursion: Only one layer is unpacked, and to unpack the entire error chain, you need to call it loop
  • Cooperate with /As: and the error chain will be automatically handled internally

Use scenarios

  • Check the error chain layer by layer through loop call to iterate through all nested errors:
currentErr := err
for currentErr != nil {
    (currentErr)
    currentErr = (currentErr)
}
  • Combining ** and ** Although both will automatically traverse the error chain, Unwrap can be used in conjunction with the error chain when it is necessary to manually extract specific hierarchy errors.

  • Hierarchical processing of custom error types is to implement the Unwrap() method for custom errors, so that it can be integrated into the error chain mechanism.

Things to note

  • Unpacking only one layer for each call will only return the lower layer error that is directly wrapped. The call needs to be looped to iterate through the entire chain.

  • Relying on the Unwrap() method can only be correctly unpacked if an error implements the Unwrap() error method. For example:

  • Errors using %w packages will automatically implement this method.
  • Custom errors need to be explicitly implemented Unwrap() error.
  • Null value processing If err is nil, or Unwrap is not implemented, or Unwrap returns nil, the function returns nil.

summary

It is the basic tool for handling error chains and is suitable for scenarios where errors need to be unpacked manually layer by layer. Combining and can enable more efficient and secure error checking. In actual development, the use of and Error chains is preferred, and only when direct access to specific hierarchical errors is required.

3.5 Join

Introduction

The function in Golang is an error handling tool introduced in Go 1.20, which is used to merge multiple errors into a wrapper error.

It is especially suitable for scenarios where multiple errors need to be handled simultaneously (such as multiple coroutines returning errors in concurrent operations).

Function signature

func Join(errs ...error) error
  • Parameter errs …error: A list of variable parameters that receives multiple values ​​of error type.
  • Return Value If there is at least one non-nil error in the input errs, a merged wrapper error is returned; otherwise, nil is returned.

Core functions

  • Merging multiple errors All non-nil errors merge into a single wrapper error. The merged error can be obtained by getting the slice of all the original errors.
  • Compatible and merged errors support checking or extracting specific errors in it through and. For example:
  • (err, target): Return true if there is an error matching target in the merged error chain.
  • (err, &target): An error of the first matching type in the merge error chain can be extracted.
  • Error message stitching and merged error messages are splicing of multiple original error messages, separated by newline characters. For example:
err1 := ("error 1")
err2 := ("error 2")
joinedErr := (err1, err2)
(joinedErr)
// Output:// error 1
// error 2
Sample code
package main

import (
    "errors"
    "fmt"
    "io/fs"
    "os"
)

func main() {
    err1 := ("file not found")

    // Create an error    pathErr := &{
        Op:   "open",
        Path: "/etc/passwd",
        Err:  ,
    }
    err2 := ("operation failed: %w", pathErr)

    // Merge multiple errors    joinedErr := (err1, err2)

    // Print merged error message    ("Joined error:")
    (joinedErr)

    // Check whether a specific error is included    if (joinedErr, err1) {
        ("Found 'file not found' error")
    }

    // Extract a type in the error chain    var targetErr *
    if (joinedErr, &targetErr) {
        ("Found PathError:", targetErr)
    }
}

Run output:

Joined error:
file not found
operation failed: open /etc/passwd: permission denied
Found 'file not found' error
Found PathError: open /etc/passwd: permission denied

Use scenarios

  • Errors in Concurrent Operations Collected When multiple coroutines execute concurrently, you can use to collect errors returned by all coroutines:
func processTasks(tasks []Task) error {
    var wg 
    var mu 
    var errs []error

    for _, task := range tasks {
        (1)
        go func(t Task) {
            defer ()
            if err := (); err != nil {
                ()
                errs = append(errs, err)
                ()
            }
        }(task)
    }

    ()
    return (errs...)
}
  • Summary of errors in batch operations For example, when processing multiple files or requests, all errors are returned uniformly:
func batchProcess(files []string) error {
    var errs []error
    for _, file := range files {
        if err := processFile(file); err != nil {
            errs = append(errs, ("process %s: %w", file, err))
        }
    }
    return (errs...)
}
  • Compatible with existing error handling logic, errors after merged can still be processed and without modifying existing code.

Things to note

  • Go version requirements Only available in Go 1.20 and above.

  • Empty parameter processing If all input errors are nil, return nil.

  • Error Unpacking Use Unpacking and merged errors will return a []error slice (including all non-nil errors).

  • The order of errors after the merged error sequence is the same as the order of input parameters, but and checks all errors in order.

summary

A concise way to merge multiple errors into one is provided, especially for scenarios where multiple error messages need to be aggregated (such as concurrent programming or batch processing). By combining and , specific errors in the merged error chain can be flexibly checked or extracted. It is an important addition to the Go error handling toolbox, further improving the convenience of error management.

4. Summary

The errors package is the core package used for error handling in the Go language standard library, and as the Go version evolves, it provides increasingly powerful error handling capabilities.

Here is a summary of the main functions:

  • Basic error creation
  • New(text string) error: Create a simple error object
  • Example: err := ("file not found")
  • Error check
  • Is(err, target error) bool: Check whether the error chain contains a specific error
  • Example: if (err, ) {…}
  • Error type extraction
  • As(err error, target interface{}) bool: Extract a specific type of error from the error chain
  • Example: var perr *; if (err, &perr) {…}
  • Error packaging and unpacking
  • Unwrap(err error) error: Unwrap a layer error
  • %w verb packaging error by
  • Example: wrapped := ("context: %w", err)
  • Error combination
  • Join(errs …error) error (Go 1.20+): Merge multiple errors into one combination error
  • Example: combined := (err1, err2, err3)

The errors package is used in conjunction with other error types (such as , , etc.) in the standard library to form a powerful error handling system in Go.

References

/errors

This is the end of this article about getting started with Golang errors package quickly. For more information about Golang errors package, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!