0 Tage Serie
go / expert
Snippet

Fehlerketten mit errors.As und Unwrap auswerten

Erfahrene Go-Fehlerbehandlung schichtet Kontext um die eigentliche Ursache: fmt.Errorf mit %w sowie eigene Typen mit Unwrap()-Methode. errors.As durchläuft die Kette und kopiert den ersten passenden typisierten Fehler in den Zielzeiger, sodass Felder wie Op und Path zugänglich werden. errors.Is durchläuft dieselbe Kette und vergleicht gegen Sentinel-Werte. Zusammen erlauben sie Verzweigungen anhand von Struktur oder Identität — ohne fragile String-Vergleiche und ohne den Originalfehler zu verlieren.

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
package main
import (
"errors"
"fmt"
"os"
)
type PathError struct {
Op string
Path string
Err error
}
func (e *PathError) Error() string {
return e.Op + " " + e.Path + ": " + e.Err.Error()
}
func (e *PathError) Unwrap() error { return e.Err }
func openConfig() error {
return &PathError{Op: "open", Path: "/etc/app.conf",
Err: fmt.Errorf("stat: %w", os.ErrNotExist)}
}
func main() {
err := openConfig()
var pe *PathError
if errors.As(err, &pe) {
fmt.Println("op:", pe.Op, "path:", pe.Path)
}
if errors.Is(err, os.ErrNotExist) {
fmt.Println("missing — using defaults")
}
}
Erklärung
1
func (e *PathError) Unwrap() error { return e.Err }
Die Unwrap-Methode auf dem Zeiger-Empfänger hängt PathError in die errors.Is/As-Traversierung ein, sodass die Ursache inspizierbar bleibt.
2
Err: fmt.Errorf("stat: %w", os.ErrNotExist)
Das %w-Verb umhüllt das Sentinel os.ErrNotExist und erzeugt eine zweistufige Kette: PathError → fmt-Fehler → os.ErrNotExist.
3
if errors.As(err, &pe) {
errors.As durchsucht die Kette und weist den ersten gefundenen *PathError der Variable pe zu — ohne Type-Assertion oder String-Parsing.
4
if errors.Is(err, os.ErrNotExist) {
errors.Is wandert auch hinter die PathError-Schicht und trifft das tief verpackte Sentinel — saubere Fallback-Logik wird möglich.