or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

apidiff.mdconstraints.mdebnf.mderrors.mdevent.mdgorelease.mdindex.mdio-i2c.mdio-spi.mdjsonrpc2.mdmaps.mdmmap.mdmodgraphviz.mdrand.mdshiny.mdslices.mdslog.mdstats.mdsumdb.mdtrace.mdtxtar.mdtypeparams.mdutf8string.md
tile.json

errors.mddocs/

golang.org/x/exp/errors

Package errors implements functions to manipulate errors according to the Go 2 draft designs for error inspection and printing. This is an experimental package that provides advanced error handling capabilities including error wrapping, inspection, and custom error formatting.

Package Information

  • Package Name: golang.org/x/exp/errors
  • Package Type: Go (golang)
  • Language: Go
  • Status: Experimental (may change without notice)
  • Installation: go get golang.org/x/exp/errors
  • Reference: https://go.googlesource.com/proposal/+/master/design/go2draft.md

Core Imports

import "golang.org/x/exp/errors"

For the fmt subpackage:

import "golang.org/x/exp/errors/fmt"

Basic Usage

package main

import (
	"fmt"
	"golang.org/x/exp/errors"
)

// Create new errors with stack frames
err := errors.New("operation failed")

// Wrap errors with context
wrappedErr := fmt.Errorf("failed to process: %w", err)

// Check if an error matches a type
var customErr CustomError
if errors.As(wrappedErr, &customErr) {
	fmt.Println("Found custom error")
}

// Check if an error is a specific instance
if errors.Is(wrappedErr, err) {
	fmt.Println("Error chain contains original error")
}

// Inspect error chains with detail
fmt.Printf("%+v\n", wrappedErr)

Capabilities

Error Creation and Basic Operations

Create new errors with caller location information and manipulate error chains.

func New(text string) error

New returns an error that formats as the given text. The returned error embeds a Frame set to the caller's location and implements Formatter to show this information when printed with details.

func Unwrap(err error) error

Unwrap returns the next error in err's chain. If there is no next error, Unwrap returns nil.

func Opaque(err error) error

Opaque returns an error with the same error formatting as err but that does not match err and cannot be unwrapped. This is useful for breaking error chains when needed.

Error Inspection

Inspect and match errors in an error chain to determine their types and values.

func Is(err, target error) bool

Is returns true if any error in err's chain matches target. An error is considered to match a target if it is equal to that target or if it implements an Is method such that Is(target) returns true.

func As(err error, target interface{}) bool

As finds the first error in err's chain that matches a type to which target points, and if so, sets the target to its value and reports success. An error matches a type if it is of the same type, or if it has an As method such that As(target) returns true. As will panic if target is nil or not a pointer.

The As method should set the target to its value and report success if err matches the type to which target points.

Stack Frame Information

Capture and format stack frame information for detailed error reporting.

func Caller(skip int) Frame

Caller returns a Frame that describes a frame on the caller's stack. The argument skip is the number of frames to skip over. Caller(0) returns the frame for the caller of Caller.

func (f Frame) Format(p Printer)

Format prints the stack as error detail. It should be called from an error's Format implementation, before printing any other error detail.

Types

Formatter Interface

type Formatter interface {
	error
	FormatError(p Printer) (next error)
}

A Formatter formats error messages. The FormatError method prints the receiver's first error and returns the next error in the error chain, if any. This interface is used to customize error formatting with detailed information.

Frame Type

type Frame struct {
	// Has unexported fields.
}

A Frame contains part of a call stack. It captures location information that can be used in custom error formatting.

Printer Interface

type Printer interface {
	Print(args ...interface{})
	Printf(format string, args ...interface{})
	Detail() bool
}

A Printer formats error messages. The most common implementation of Printer is the one provided by package fmt during Printf. Localization packages such as golang.org/x/text/message typically provide their own implementations.

  • Print: Appends args to the message output.
  • Printf: Writes a formatted string.
  • Detail: Reports whether error detail is requested. After the first call to Detail, all text written to the Printer is formatted as additional detail, or ignored when detail has not been requested. If Detail returns false, the caller can avoid printing the detail at all.

Wrapper Interface

type Wrapper interface {
	Unwrap() error
}

A Wrapper provides context around another error. Any error that implements the Unwrap method is considered a Wrapper and can be inspected with the Is and As functions.

Advanced Usage Examples

Custom Error Wrapping

package main

import (
	"golang.org/x/exp/errors"
	"fmt"
)

func processData(data string) error {
	if data == "" {
		return errors.New("data cannot be empty")
	}
	return nil
}

func main() {
	err := processData("")
	if err != nil {
		wrapped := fmt.Errorf("processing failed: %w", err)
		fmt.Printf("%v\n", wrapped)
		fmt.Printf("%+v\n", wrapped) // With stack trace
	}
}

Type-based Error Inspection

package main

import (
	"golang.org/x/exp/errors"
)

type ValidationError struct {
	Field   string
	Message string
}

func (ve *ValidationError) Error() string {
	return ve.Field + ": " + ve.Message
}

func validateInput(input string) error {
	if len(input) < 5 {
		return &ValidationError{
			Field:   "input",
			Message: "must be at least 5 characters",
		}
	}
	return nil
}

func main() {
	err := validateInput("hi")

	var valErr *ValidationError
	if errors.As(err, &valErr) {
		println("Validation failed on field:", valErr.Field)
	}
}

Error Chain Inspection

package main

import (
	"golang.org/x/exp/errors"
	"fmt"
)

func main() {
	originalErr := errors.New("original error")
	wrappedErr := fmt.Errorf("operation failed: %w", originalErr)

	// Check if chain contains original error
	if errors.Is(wrappedErr, originalErr) {
		println("Chain contains original error")
	}

	// Unwrap to get next error in chain
	next := errors.Unwrap(wrappedErr)
	if next != nil {
		println("Next error:", next.Error())
	}
}

errors/fmt Subpackage

The errors/fmt subpackage implements formatted I/O with special support for errors.Formatter interface.

fmt Imports

import "golang.org/x/exp/errors/fmt"

fmt Functions

func Errorf(format string, a ...interface{}) error

Errorf formats according to a format specifier and returns the string as a value that satisfies error. The returned error includes the file and line number of the caller when formatted with additional detail enabled. If the last argument is an error, the returned error's Format method will return it if the format string ends with ": %s", ": %v", or ": %w". If the last argument is an error and the format string ends with ": %w", the returned error implements errors.Wrapper with an Unwrap method returning it.

func Fprint(w io.Writer, a ...interface{}) (n int, err error)

Fprint formats using the default formats for its operands and writes to w. Spaces are added between operands when neither is a string. It returns the number of bytes written and any write error encountered.

func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)

Fprintf formats according to a format specifier and writes to w. It returns the number of bytes written and any write error encountered.

func Fprintln(w io.Writer, a ...interface{}) (n int, err error)

Fprintln formats using the default formats for its operands and writes to w. Spaces are always added between operands and a newline is appended. It returns the number of bytes written and any write error encountered.

func FormatError(s State, verb rune, err errors.Formatter)

FormatError calls the FormatError method of err with an errors.Printer configured according to s and verb and writes the result to s.

func Print(a ...interface{}) (n int, err error)

Print formats using the default formats for its operands and writes to standard output. Spaces are added between operands when neither is a string. It returns the number of bytes written and any write error encountered.

func Printf(format string, a ...interface{}) (n int, err error)

Printf formats according to a format specifier and writes to standard output. It returns the number of bytes written and any write error encountered.

func Println(a ...interface{}) (n int, err error)

Println formats using the default formats for its operands and writes to standard output. Spaces are always added between operands and a newline is appended. It returns the number of bytes written and any write error encountered.

func Sprint(a ...interface{}) string

Sprint formats using the default formats for its operands and returns the resulting string. Spaces are added between operands when neither is a string.

func Sprintf(format string, a ...interface{}) string

Sprintf formats according to a format specifier and returns the resulting string.

func Sprintln(a ...interface{}) string

Sprintln formats using the default formats for its operands and returns the resulting string. Spaces are always added between operands and a newline is appended.

func Fscan(r io.Reader, a ...interface{}) (n int, err error)

Fscan scans text read from r, storing successive space-separated values into successive arguments. Newlines count as space. It returns the number of items successfully scanned. If that is less than the number of arguments, err will report why.

func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)

Fscanf scans text read from r, storing successive space-separated values into successive arguments as determined by the format. It returns the number of items successfully parsed. Newlines in the input must match newlines in the format.

func Fscanln(r io.Reader, a ...interface{}) (n int, err error)

Fscanln is similar to Fscan, but stops scanning at a newline and after the final item there must be a newline or EOF.

func Scan(a ...interface{}) (n int, err error)

Scan scans text read from standard input, storing successive space-separated values into successive arguments. Newlines count as space. It returns the number of items successfully scanned. If that is less than the number of arguments, err will report why.

func Scanf(format string, a ...interface{}) (n int, err error)

Scanf scans text read from standard input, storing successive space-separated values into successive arguments as determined by the format. It returns the number of items successfully scanned. If that is less than the number of arguments, err will report why. Newlines in the input must match newlines in the format.

func Scanln(a ...interface{}) (n int, err error)

Scanln is similar to Scan, but stops scanning at a newline and after the final item there must be a newline or EOF.

func Sscan(str string, a ...interface{}) (n int, err error)

Sscan scans the argument string, storing successive space-separated values into successive arguments. Newlines count as space. It returns the number of items successfully scanned. If that is less than the number of arguments, err will report why.

func Sscanf(str string, format string, a ...interface{}) (n int, err error)

Sscanf scans the argument string, storing successive space-separated values into successive arguments as determined by the format. It returns the number of items successfully parsed. Newlines in the input must match newlines in the format.

func Sscanln(str string, a ...interface{}) (n int, err error)

Sscanln is similar to Sscan, but stops scanning at a newline and after the final item there must be a newline or EOF.

fmt Types

type Formatter interface {
	Format(f State) string
}

Formatter is the interface implemented by values with a custom formatter. The implementation of Format may call Sprint(f) or Fprint(f) etc. to generate its output.

type GoStringer interface {
	GoString() string
}

GoStringer is implemented by any value that has a GoString method, which defines the Go syntax for that value. The GoString method is used to print values passed as an operand to a %#v format.

type ScanState interface {
	ReadRune() (r rune, size int, err error)
	UnreadRune() error
	SkipSpace()
	Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
	Width() (wid int, ok bool)
	Read(buf []byte) (n int, err error)
}

ScanState represents the scanner state passed to custom scanners. Scanners may do rune-at-a-time scanning or ask the ScanState to discover the next space-delimited token.

type Scanner interface {
	Scan(state ScanState, verb rune) error
}

Scanner is implemented by any value that has a Scan method, which scans the input for the representation of a value and stores the result in the receiver, which must be a pointer to be useful. The Scan method is called for any argument to Scan, Scanf, or Scanln that implements it.

type State interface {
	Write(b []byte) (n int, err error)
	Width() (wid int, ok bool)
	Precision() (prec int, ok bool)
	Flag(c int) bool
}

State represents the printer state passed to custom formatters. It provides access to the io.Writer interface plus information about the flags and options for the operand's format specifier.

type Stringer interface {
	String() string
}

Stringer is implemented by any value that has a String method, which defines the "native" format for that value. The String method is used to print values passed as an operand to any format that accepts a string or to an unformatted printer such as Print.

Format Verbs

The fmt subpackage supports the following format verbs:

  • %v - default format
  • %#v - Go-syntax representation
  • %T - Go-syntax type representation
  • %s - string
  • %d - decimal integer
  • %x, %X - hexadecimal
  • %o - octal
  • %b - binary
  • %c - character
  • %e, %E - scientific notation
  • %f, %F - floating-point
  • %g, %G - floating-point (compact)
  • %p - pointer address

Implementation Notes

  1. Experimental Status: This package implements Go 2 draft designs and may change without notice. Do not rely on API stability in production code.

  2. Error Formatting: When an error implements the Formatter interface, the fmt package will call its FormatError method with a Printer to control output formatting.

  3. Stack Traces: Errors created with errors.New() automatically capture stack frame information that can be printed with %+v.

  4. Error Chains: The Is and As functions traverse error chains created with fmt.Errorf using the %w verb, allowing deep inspection of wrapped errors.

  5. Opaque Errors: The Opaque function breaks error chains, preventing Is/As from traversing past the opaque error while preserving error formatting.

Error Handling Patterns

Safe Error Type Assertion

Always use As for safe type assertion instead of type switches:

var err error
var unwantedErr UnwantedError

if errors.As(err, &unwantedErr) {
	// Handle specific error type safely
}

Chain Inspection

Use Is to check if an error is anywhere in the chain:

originalErr := errors.New("original")
wrapped := fmt.Errorf("wrapper: %w", originalErr)

if errors.Is(wrapped, originalErr) {
	// True: originalErr is in the chain
}

Custom Formatter Implementation

Implement Formatter for detailed error reporting:

type MyError struct {
	message string
	frame   errors.Frame
}

func (me *MyError) FormatError(p errors.Printer) (next error) {
	me.frame.Format(p)
	p.Printf("%s", me.message)
	return nil
}