Skip to content
Skip to content
DocsGo LearningintermediateError Handling
Chapter 7 of 14·intermediate·7 min read

Error Handling

Xử Lý Lỗi

error type, wrapping, errors.Is/As, and panic/recover

Hover or tap any paragraph to see Vietnamese translation

The error Type

error is a built-in interface in Go with a single method: Error() string. Any type implementing this method is an error. Go handles errors through return values — functions return (result, error) and callers should check if err != nil at each call site.

error_type.go
1package main23import (4    "errors"5    "fmt"6)78// error interface is defined as:9// type error interface {10//     Error() string11// }12

fmt.Errorf with %w — Wrapping Errors

When propagating errors up the stack, add context with fmt.Errorf and %w (wrap). %w lets you wrap the original error in a new message. This creates an error chain that you can inspect piece by piece using errors.Is and errors.As.

wrap_errors.go
1package main23import (4    "errors"5    "fmt"6    "os"7)89// readConfig reads a config file and returns an error if it fails10func readConfig(path string) (string, error) {11    content, err := os.ReadFile(path)12    if err != nil {

errors.Is and errors.As

errors.Is compares an error to a sentinel error by walking the wrap chain. errors.As searches for an error of a specific type in the chain and extracts it. This allows fine-grained error handling even when errors are wrapped deeply.

errors_is_as.go
1package main23import (4    "errors"5    "fmt"6)78// Define sentinel errors at package level9var (10    ErrNotFound = errors.New("resource not found")11    ErrPermissionDenied = errors.New("permission denied")12)
Warning
Define sentinel errors at package level with var ErrXxx = errors.New(...). This allows callers to compare using errors.Is.

Custom Error Types

For fine-grained error handling, define your own custom error types by implementing the Error() method. Custom error types can contain additional information like status codes, validation fields, etc.

custom_errors.go
1package main23import (4    "fmt"5)67// Custom error with HTTP status code8type HTTPError struct {9    Code    int10    Message string11}12

panic and recover

panic is used for truly unrecoverable situations — contract violations or broken invariants. recover() is called in a deferred function to catch a panic and regain control. However, do not use panic/recover for normal control flow — use error types instead.

panic_recover.go
1package main23import (4    "fmt"5)67// safeDiv panics on division by zero but recovers gracefully8func safeDiv(a, b int) (result int) {9    defer func() {10        if r := recover(); r != nil {11            fmt.Println("Caught panic:", r)12            result = 0
Warning
Only use panic for genuinely unrecoverable situations (initialization errors, contract violations). For recoverable errors, return an error type.

Error Handling Patterns

Wrap on the way up, check at the boundary

When an error occurs at a low level, wrap it with context as you propagate it up. Only handle (log, return to user, etc.) at the boundary of your application — for example in a route handler or main function.

wrap_pattern.go
1package main23import (4    "errors"5    "fmt"6)78// Low-level function — just return error as-is or wrap with context9func readDatabase() (string, error) {10    return "", errors.New("connection failed")11}12

Use Sentinel Errors for Expected Cases

  • Define sentinel errors at package level for expected error cases: var ErrNotFound = errors.New(...)
  • Use errors.Is(err, ErrNotFound) to check and handle specific cases
  • Use custom errors (structs) for errors with extra information (status code, field, etc.)

Key Takeaways

Điểm Chính

  • error is an interface; any type with Error() string method is an errorerror là interface; bất kỳ kiểu nào có phương thức Error() string đều là error
  • Use fmt.Errorf with %w to wrap errors with context, creating error chainsDùng fmt.Errorf với %w để bao bọc lỗi với bối cảnh, tạo chuỗi lỗi
  • Use errors.Is for sentinel errors and errors.As to extract specific error typesDùng errors.Is cho sentinel error và errors.As để trích xuất kiểu lỗi cụ thể
  • panic/recover are for unrecoverable situations; use error types for normal error handlingpanic/recover là cho tình huống không thể khôi phục; dùng error type cho xử lý lỗi bình thường

Practice

Test your understanding of this chapter

Quiz

What is the standard Go idiom for checking if an operation succeeded or failed?

Thành ngữ chuẩn Go để kiểm tra xem hoạt động có thành công hay thất bại là gì?

Quiz

What is the purpose of the %w verb in fmt.Errorf?

Mục đích của %w trong fmt.Errorf là gì?

True or False

In Go, panic should be used for all error cases to ensure the program stops immediately and safely.

Trong Go, panic nên được dùng cho tất cả các trường hợp lỗi để đảm bảo chương trình dừng lại ngay lập tức và an toàn.

True or False

The errors.Is function can detect a sentinel error even if it is wrapped multiple times in an error chain.

Hàm errors.Is có thể phát hiện sentinel error ngay cả khi nó được bao bọc nhiều lần trong chuỗi lỗi.

Code Challenge

Complete the error wrapping pattern

Hoàn thành mô hình bao bọc lỗi

func readConfig(path string) (string, error) {
    content, err := os.ReadFile(path)
    if err != nil {
        return "", ("failed to read config: %w", )
    }
    return string(content), nil
}
Built: 6/25/2026, 3:03:36 PM