0 day streak
go / intermediate
Snippet

Retrieving Rich Context via Custom Error Structs and Unwrapping

In Go, errors can wrap other errors to provide contextual information while preserving the original error's type and details. By implementing the Unwrap() error method on a custom error struct, you allow functions like errors.Is and errors.As to inspect the error chain. This enables decoupled error handling where callers can inspect deep errors without tight coupling to the wrapper.

snippet.go
go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main
import (
"errors"
"fmt"
)
type QueryError struct {
Query string
Err error
}
func (e *QueryError) Error() string {
return fmt.Sprintf("query %q failed: %v", e.Query, e.Err)
}
func (e *QueryError) Unwrap() error {
return e.Err
}
func executeQuery(query string) error {
return &QueryError{
Query: query,
Err: errors.New("connection timeout"),
}
}
func main() {
err := executeQuery("SELECT * FROM users")
if err != nil {
var qErr *QueryError
if errors.As(err, &qErr) {
fmt.Printf("Custom error caught! Query: %s\n", qErr.Query)
}
}
}
Breakdown
1
type QueryError struct {
Declares a custom error struct containing metadata (the query) and the underlying wrapped error.
2
func (e *QueryError) Error() string {
Implements the error interface, allowing QueryError to be used as a standard Go error.
3
func (e *QueryError) Unwrap() error {
Returns the nested error, enabling the standard library's error inspection helpers to traverse the chain.
4
if errors.As(err, &qErr) {
Checks if any error in the chain is of type QueryError, assigning it to qErr if found.