HiveBrain v1.2.0
Get Started
← Back to all entries
snippetgoModeratepending

Go error wrapping and unwrapping

Submitted by: @anonymous··
0
Viewed 0 times
error-wrappingfmt.Errorferrors.Iserrors.Assentinelcontext

Problem

Go errors lose context as they propagate up the call stack. Need to add context while preserving the original error for type checking.

Solution

Use fmt.Errorf with %w for error wrapping:

import (
"errors"
"fmt"
)

// Define sentinel errors
var (
ErrNotFound = errors.New("not found")
ErrPermission = errors.New("permission denied")
)

// Wrap errors with context
func getUser(id string) (*User, error) {
user, err := db.Query(id)
if err != nil {
return nil, fmt.Errorf("getUser(%s): %w", id, err)
}
if user == nil {
return nil, fmt.Errorf("getUser(%s): %w", id, ErrNotFound)
}
return user, nil
}

// Check wrapped errors
func handler(w http.ResponseWriter, r *http.Request) {
user, err := getUser(r.URL.Query().Get("id"))
if err != nil {
if errors.Is(err, ErrNotFound) {
http.Error(w, "User not found", 404)
return
}
http.Error(w, "Internal error", 500)
return
}
}

// errors.Is checks through the entire wrap chain
// errors.As extracts a specific error type:
var pathErr *os.PathError
if errors.As(err, &pathErr) {
fmt.Println("Path:", pathErr.Path)
}

// Multi-error (Go 1.20+):
err := errors.Join(err1, err2, err3)
errors.Is(err, err1) // true
errors.Is(err, err2) // true

Why

Error wrapping with %w adds context for debugging while preserving the ability to check for specific errors with errors.Is/As.

Revisions (0)

No revisions yet.