Fundamentals 15 min read

Master Go Error Handling: Built-in Errors, Wrapping, and Panic/Recover

This article explains Go's unique error handling approach, covering the built-in error interface, creating errors with errors.New, wrapping errors using fmt.Errorf, defining custom error types, logging errors with the log package, and managing severe failures with panic and recover, complete with practical code examples.

FunTester
FunTester
FunTester
Master Go Error Handling: Built-in Errors, Wrapping, and Panic/Recover

Go error handling overview

Unlike languages that use try‑catch, Go treats errors as ordinary return values. Every function that can fail returns an error alongside its regular result, and callers must check the error explicitly. This makes error handling explicit and improves code readability.

Built‑in error type

The error interface is defined in the standard library as:

type error interface {
    Error() string
}

Any type that implements Error() string satisfies the interface, allowing custom error types. The errors package provides a simple constructor:

import "errors"

err := errors.New("division by zero, please check")

Typical usage checks the returned error immediately after a call.

Error wrapping (Go 1.13)

Go 1.13 introduced the %w verb in fmt.Errorf, which wraps an existing error while preserving its original value. Wrapped errors carry additional context for easier debugging.

import (
    "errors"
    "fmt"
)

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, fmt.Errorf("division error: %w", errors.New("divisor cannot be zero"))
    }
    return a / b, nil
}

Custom error types

Developers can define structs that implement the Error() method to attach extra information such as codes, timestamps, or domain‑specific fields.

package main

import (
    "fmt"
)

type FunTesterError struct {
    Reason string
}

func (e *FunTesterError) Error() string {
    return fmt.Sprintf("%s is fun", e.Reason)
}

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, &FunTesterError{Reason: "I am fun"}
    }
    return a / b, nil
}

func main() {
    result, err := divide(8, 0)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Result:", result)
}

The custom type implements error, so it can be returned and inspected like any other error.

Error logging

The built‑in log package provides a straightforward way to record errors, which is essential for monitoring production systems.

package main

import (
    "errors"
    "fmt"
    "log"
)

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("divisor cannot be zero, please check")
    }
    return a / b, nil
}

func main() {
    result, err := divide(4, 0)
    if err != nil {
        log.Printf("Error: %s", err)
        return
    }
    fmt.Println("Result:", result)
}

Panic and recover

For unrecoverable situations Go provides panic, which aborts normal flow and unwinds the stack, executing any deferred functions. recover can be called inside a defer to capture the panic value and resume execution.

panic

package main

import (
    "fmt"
    "log"
)

func divide(a, b int) int {
    if b == 0 {
        panic("divisor cannot be zero, please check")
    }
    return a / b
}

func main() {
    defer func() {
        if r := recover(); r != nil {
            log.Printf("Recovered from panic: %v", r)
        }
    }()
    fmt.Println(divide(4, 0))
    fmt.Println("Program exits normally")
}

Best practice

Reserve panic for truly exceptional conditions (e.g., out‑of‑bounds access, nil‑pointer dereference). Use regular error returns for expected failures. recover should be used sparingly, typically in top‑level handlers, to log the issue and perform cleanup before terminating or continuing safely.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

GologgingError Handlingcustom errorpanicrecover
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

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.