Backend Development 5 min read

Error Handling in Go Before and After Go 1.13

This article explains Go's built‑in error interface, the traditional ways of creating and checking errors before Go 1.13, and the new errors.Unwrap, errors.Is, errors.As functions plus the %w verb in fmt.Errorf introduced in Go 1.13 for error wrapping and inspection.

System Architect Go
System Architect Go
System Architect Go
Error Handling in Go Before and After Go 1.13

In Go, type error interface { Error() string } is the built‑in error type. Before Go 1.13, errors were created mainly with errors.New and fmt.Errorf , and developers checked them by comparing with nil or specific error values.

Typical patterns include:

if err != nil {
    // something went wrong
}

var ErrNotFound = errors.New("not found")
if err == ErrNotFound {
    // handle not‑found case
}

Because error is an interface, you can define custom error types that implement the Error() method, allowing type assertions to retrieve additional context:

type NotFoundError struct { Name string }
func (e *NotFoundError) Error() string { return e.Name + ": not found" }
if e, ok := err.(*NotFoundError); ok {
    // handle specific error
}

Developers often wrap errors with extra context using fmt.Errorf("context %v: %v", name, err) , but this does not preserve a link to the original error.

Go 1.13 introduced three new utilities in the errors package:

func Unwrap(err error) error – returns the underlying error.

func Is(err, target error) bool – reports whether any error in err's chain matches target.

func As(err error, target interface{}) bool – finds the first error in the chain that can be assigned to target.

Additionally, fmt.Errorf gained the %w verb, which creates a wrapped error that automatically implements Unwrap :

if err != nil {
    return fmt.Errorf("error context %v: %w", name, err)
}

With %w , the wrapped error can be inspected using errors.Is and errors.As :

err := fmt.Errorf("access denied: %w", ErrPermission)
if errors.Is(err, ErrPermission) {
    // handle permission error
}
var q *QueryError
if errors.As(err, &q) {
    // err is a *QueryError
}

These improvements simplify error chaining, inspection, and handling, while older pre‑1.13 patterns remain valid and backward compatible.

Reference: Go 1.13 Errors Blog

Goerror handlingaserrors-packagefmtgo1.13isunwrap
System Architect Go
Written by

System Architect Go

Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.