Przejdź do treści
Biblioteka skilli
Programowanie · Nauka i wyjaśnianie

go-error-handling

/go-error-handling

Podaje wzorce obsługi błędów w Go: opakowywanie, błędy sentinel, własne typy błędów i pakiet errors, oparte na Effective Go i Go Code Review Comments.

Licencja
MIT
Ostatnia zmiana repozytorium
15.10.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
2
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 15.10.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Podaje wzorce obsługi błędów w Go: opakowywanie, błędy sentinel, własne typy błędów i pakiet errors, oparte na Effective Go i Go Code Review Comments.

Wyzwalacze z opisu

handle errorserror wrappingcustom error typesentinel errorserrors.Iserrors.As
Oryginalny opis (EN)

Go error handling patterns, wrapping, sentinel errors, custom error types, and the errors package. Grounded in Effective Go, Go Code Review Comments, and production-proven idioms. Use when implementing error handling, designing error types, debugging error chains, or reviewing error handling patterns. Trigger examples: "handle errors", "error wrapping", "custom error type", "sentinel errors", "errors.Is", "errors.As". Not for: panic/recover in middleware (go-api-design), test assertions (go-test-quality).

Jak działa

  1. 1. Error Decision Tree
  2. 2. Sentinel Errors
  3. 3. Custom Error Types
  4. 4. Error Wrapping
  5. 5. Handle Errors Exactly Once
  6. 6. Error Naming Conventions
  7. 7. Panic Rules
  8. 8. Error Checking Patterns
  9. 9. Errors at Boundaries
  10. Executable Verification
Sekcje z nagłówków SKILL.md, w oryginale · 229 linii, 1 106 słów
Podgląd SKILL.md
---
name: go-error-handling
description: >
  Go error handling patterns, wrapping, sentinel errors, custom error types,
  and the errors package. Grounded in Effective Go, Go Code Review Comments,
  and production-proven idioms. Use when implementing error handling,
  designing error types, debugging error chains, or reviewing error handling
  patterns. Trigger examples: "handle errors", "error wrapping", "custom
  error type", "sentinel errors", "errors.Is", "errors.As".
  Not for: panic/recover in middleware (go-api-design), test assertions
  (go-test-quality).
user-invocable: true
license: MIT
compatibility: Designed for Claude Code or similar AI coding agents working on Go projects. Requires the Go toolchain.
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(gofmt:*)
metadata:
  author: eduardo-sl
  version: "1.3.1"
---

# Go Error Handling

Go's explicit error handling is a feature, not a limitation.
These patterns ensure errors are informative, actionable, and properly propagated.

> Community default. A project skill or agent-config rule that explicitly
> supersedes `go-error-handling` takes precedence over this one.

Detailed reference material, loaded on demand:

- `references/patterns-and-boundaries.md` — checking patterns, `Is`
  methods, translating errors at the HTTP boundary, low-cardinality logging,
  the Go 1.27 vet check on `%w` with pointer errors.

Read a reference file only when the summary below is not enough.

## 1. Error Decision Tree

When creating or returning an error, follow this tree:

1. **Simple, no extra context needed?** → `errors.New("message")`
2. **Need to add context to existing error?** → `fmt.Errorf("doing X: %w", err)`
3. **Caller needs to detect this error?** → Sentinel `var` or custom type
4. **Error carries structured data?** → Custom type implementing `error`
5. **Propagating from downstream?** → Wrap with `%w` and add context

## 2. Sentinel Errors

Use package-level `var` for errors that callers need to check:

```go
// ✅ Good — exported sentinel error
var (
    ErrNotFound     = errors.New("user: not found")
    ErrUnauthorized = errors.New("user: unauthorized")
)

// Naming convention: Err + Description
// Prefix with package context in the message
```

Callers check with `errors.Is`:

```go
if errors.Is(err, user.ErrNotFound) {
    // handle not found
}
```

NEVER compare errors with `==`. Always use `errors.Is()`.

## 3. Custom Error Types

When errors need to carry structured information:

```go
type ValidationError struct {
    Field   string
    Message string
}

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

// Callers extract it from the chain — Go 1.26+:
if valErr, ok := errors.AsType[*ValidationError](err); ok {
    log.Printf("invalid field: %s", valErr.Field)
}

// Before Go 1.26:
var valErr *ValidationError
if errors.As(err, &valErr) {
    log.Printf("invalid field: %s", valErr.Field)
}
```

A custom type that wraps a cause must expose it, or `errors.Is`/`errors.As`
stop at your type and never see the error underneath:

```go
type QueryError struct {
    Query string
    Err   error
}

func (e *QueryError) Error() string { return "query " + e.Query + ": " + e.Err.Error() }
func (e *QueryError) Unwrap() error { return e.Err } // keeps the chain walkable
```

## 4. Error Wrapping

ALWAYS add context when propagating errors up the stack.
Use `%w` to preserve the error chain:

```go
// ✅ Good — context added, chain preserved
func getUser(id int64) (*User, error) {
    row, err := db.QueryRow(ctx, query, id)
    if err != nil {
        return nil, fmt.Errorf("get user %d: %w", id, err)
    }
    // ...
}

// ❌ Bad — no context
return nil, err

// ❌ Bad — chain broken, callers can't errors.Is/As
return nil, fmt.Errorf("failed: %v", err)
```

### When NOT to use `%w`

Use `%v` instead of `%w` when you explicitly want to **break** the error chain,
preventing callers from depending on internal implementation errors:

```go
// Intentionally hiding internal DB error from public API
return nil, fmt.Errorf("user lookup failed: %v", err)
```

## 5. Handle Errors Exactly Once

An error should be either logged OR returned, never both:

```go
// ✅ Good — return the error, let caller decide
func loadConfig(path string) (*Config, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return nil, fmt.Errorf("load config %s: %w", path, err)
    }
    // ...
}

// ❌ Bad — log AND return (error handled twice)
func loadConfig(path string) (*Config, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        log.Printf("failed to read config: %v", err) // handled once
        return nil, err                                 // handled again
    }
    // ...
}
```

The rule: the component that *decides what to do* about the error is the one
that logs/metrics it. Everyone else wraps and returns.

## 6. Error Naming Conventions

```go
// Sentinel errors: Err prefix
var ErrNotFound = errors.New("not found")

// Error types: Error suffix
type NotFoundError struct { ... }
type ValidationError struct { ... }

// Error messages: lowercase, no punctuation, no "failed to" prefix
// Include context: "package: action: detail"
errors.New("auth: token expired")
fmt.Errorf("user: get by id %d: %w", id, err)
```

## 7. Panic Rules

Panic is NOT error handling. Use panic only when:
- Program initialization fails and cannot continue (`template.Must`, flag parsing)
- Programmer error that should never happen (violated invariant)
- Nil dereference that indicates a bug, not a runtime condition

In tests, use `t.Fatal` / `t.FailNow`, never `panic`.

In HTTP handlers and middleware, recover from panics at the boundary
to prevent one request from crashing the server.

## 8. Error Checking Patterns

- Scope the error to the `if` when nothing else needs it:
  `if err := do(); err != nil { return fmt.Errorf("do: %w", err) }`.
- A deferred wrap on a named `err` result adds one prefix to every return
  path of a long function.
- Collect independent failures (validation, parallel work) and return
  `errors.Join(errs...)` — `errors.Is`/`As` see every joined error.

## 9. Errors at Boundaries

- **Publishing an error is a contract.** Inside the module, wrap with `%w`.
  At a boundary you publish (an exported library API, an RPC), `%w` makes
  the wrapped error part of your API; `%v` or a new error keeps it private.
- **Translate before it reaches a user.** Map domain errors to a status
  and a stable message at the handler, and log the original once with its
  chain. `err.Error()` in a response leaks SQL, paths and hostnames.
- **Keep logged messages low-cardinality.** The stable text is the message;
  IDs, paths and counts go in structured attributes so the log backend can
  group identical failures.
- **Panics do not cross goroutines.** A `recover` only works in the
  goroutine that panicked — see go-concurrency-review.
- **Implement `Is(target error) bool`** on a type to let `errors.Is` match a
  whole family of errors against one sentinel.

Examples for sections 8 and 9: `references/patterns-and-boundaries.md`.

## Executable Verification

After writing or reviewing error handling, run the linters that prove
the rules above (skip any that is not installed and note it):

```bash
go vet ./...                                  # includes printf %w misuse
golangci-lint run --enable errcheck,errorlint # unchecked errors, %v-vs-%w,
                                              # == comparisons on errors
```

## Verification Checklist

1. No `_` discarding errors (unless explicitly justified with comment)
2. Every `fmt.Errorf` wrapping uses `%w` (or `%v` with documented reason)
3. Sentinel errors use `var Err...` naming
4. Custom error types implement `error` interface
5. Callers use `errors.Is` / `errors.As` (`errors.AsType` on Go 1.26+), never `==` or type assertion
6. Custom types that wrap a cause implement `Unwrap() error`
7. No log-and-return patterns
8. Error messages are lowercase, contextual, chain-friendly
9. No `err.Error()` text in responses to users; logged messages are stable, details are attributes
Pliki w paczce (2)
  • SKILL.md 8 KB
  • references/patterns-and-boundaries.md 2 KB

Wersje

RepozytoriumWynikLicencja
Ta strona · eduardo-sl/go-agent-skills100MIT
h0rn3t/golang-skills100Apache-2.0
muratmirgun/gophers100MIT
muratmirgun/gophers100MIT
cxuu/golang-skills100Apache-2.0
TheBushidoCollective/han95Apache-2.0

Identyczna treść występuje jeszcze w 1 innych folderach na GitHubie. Tu pokazujemy jedną, najlepiej ocenioną kopię.

Migawka bazy z 28.10.2026 · wersja paczki 9d5548f63405 (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100error-handling
    Wdraża wzorce obsługi błędów w Go: opakowywanie błędów, błędy sentinel, własne typy błędów i konwencje propagacji.
  • 100go-error-management
    Pomaga unikać typowych błędów obsługi błędów w Go: panic, opakowywanie błędów, errors.As i errors.Is, jednokrotna obsługa błędów oraz błędy z defer.
  • 100handling-rust-errors
    Opisuje wzorce obsługi błędów HASH z crate error-stack: typy Result i Report, własne błędy, change_context, attach i implementację Error trait.
  • 95rust-error-handling
    Dobiera strategię obsługi błędów w Ruście: Result, Option, panic, anyhow kontra thiserror oraz własne typy błędów.
  • 90golang-error-handling
    Podpowiada idiomatyczną obsługę błędów w Go: opakowywanie przez %w, errors.Is i As, logowanie przez slog i middleware HTTP.
  • 100handling-rust-errors
    Opisuje wzorce obsługi błędów HASH z użyciem crate error-stack w Rust: typy Result i Report, własne błędy, change_context, attach, trait Error i dokumentowanie warunków błędów.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.