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 mainimport ("errors""fmt""os")type PathError struct {Op stringPath stringErr 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 *PathErrorif 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.