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

Go error handling patterns and best practices

Submitted by: @anonymous··
0
Viewed 0 times
error handlingerrors.Iserrors.Aserror wrappingsentinel errorcustom error

Problem

Need idiomatic Go error handling: wrapping, custom errors, sentinel errors, and error type checking.

Solution

Go error handling patterns:

import (
	"errors"
	"fmt"
)

// 1. Sentinel errors (predefined error values)
var (
	ErrNotFound     = errors.New("not found")
	ErrUnauthorized = errors.New("unauthorized")
	ErrValidation   = errors.New("validation failed")
)

// Check with errors.Is
if errors.Is(err, ErrNotFound) {
	http.Error(w, "Not found", 404)
}

// 2. Custom error types (carry context)
type ValidationError struct {
	Field   string
	Message string
}

func (e *ValidationError) Error() string {
	return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

// Check with errors.As
var ve *ValidationError
if errors.As(err, &ve) {
	fmt.Printf("Field %s: %s\n", ve.Field, ve.Message)
}

// 3. Wrapping errors (add context while preserving original)
func getUser(id string) (*User, error) {
	row := db.QueryRow("SELECT ...")
	if err := row.Scan(&user); err != nil {
		return nil, fmt.Errorf("getUser(%s): %w", id, err)
		// %w wraps the error (errors.Is/As can unwrap it)
	}
	return &user, nil
}

// 4. Don't just check errors, handle them
// BAD: Log and return (double handling)
if err != nil {
	log.Printf("error: %v", err)  // Logged here
	return err                      // AND handled by caller
}

// GOOD: Handle at one level only
if err != nil {
	return fmt.Errorf("processing order: %w", err)  // Add context, let caller decide
}

// 5. Errors are values - use them creatively
type errWriter struct {
	w   io.Writer
	err error
}

func (ew *errWriter) write(data []byte) {
	if ew.err != nil {
		return // Skip if already errored
	}
	_, ew.err = ew.w.Write(data)
}

// Usage: check error once at the end
ew := &errWriter{w: file}
ew.write(header)
ew.write(body)
ew.write(footer)
if ew.err != nil {
	return ew.err
}

Why

Go treats errors as values, not exceptions. The explicit if err != nil pattern forces handling at each level, with wrapping providing the context trail for debugging.

Context

Go application error handling

Revisions (0)

No revisions yet.