Core Concepts
Error Handling
Handle errors the Go way — explicit, straightforward, and without exceptions.
Go's Error Philosophy
Go doesn't use exceptions. Errors are just values — functions return (result, error) and callers handle them.
This makes error handling explicit and visible in the code.
The error Interface
The built-in error interface has one method: Error() string.
Custom Errors
Create custom error types for richer error information using errors.New, fmt.Errorf, or custom structs.
Wrapping Errors
Use fmt.Errorf with %w to wrap errors (Go 1.13+). Unwrap with errors.Is and errors.As.
defer, panic, recover
defer— runs when function exits (cleanup)panic— stops normal executionrecover— catches a panic (like try/catch, use rarely)
Example
go
package main
import (
"errors"
"fmt"
)
// Sentinel errors
var ErrNotFound = errors.New("not found")
var ErrPermission = errors.New("permission denied")
// Custom error type
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation error on %s: %s", e.Field, e.Message)
}
// Function returning error
func getUser(id int) (string, error) {
if id <= 0 {
return "", &ValidationError{Field: "id", Message: "must be positive"}
}
if id > 100 {
return "", fmt.Errorf("getUser: %w", ErrNotFound)
}
return fmt.Sprintf("user_%d", id), nil
}
// defer for cleanup
func processFile(path string) error {
fmt.Println("Opening:", path)
defer fmt.Println("Closing:", path) // always runs
// ... process file
return nil
}
func main() {
// Basic error handling
user, err := getUser(42)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Got user:", user)
// Check specific error type
_, err = getUser(-1)
var validErr *ValidationError
if errors.As(err, &validErr) {
fmt.Printf("Invalid field '%s': %s\n", validErr.Field, validErr.Message)
}
// Check sentinel error
_, err = getUser(200)
if errors.Is(err, ErrNotFound) {
fmt.Println("User not found!")
}
// defer
processFile("data.txt")
// panic/recover
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
// panic("something went wrong") // would be caught
}Try it yourself — GO