Error Wrapping and Inspection
Error Wrapping
Go wraps an error with context while preserving the original cause.
wrapping
`fmt.Errorf` with `%w` adds context without discarding the error underneath.
Error Wrapping
error_wrapping.go
Replay: real traced execution (multi-file project)
package main
import (
"errors"
"fmt"
)
func main() {
var operation = "load"
base := errors.New("config missing")
wrapped := fmt.Errorf("%s failed: %w", operation, base)
fmt.Println("operation=", operation)
fmt.Println("base=", base.Error())
fmt.Println("has_error=", wrapped != nil)
fmt.Println("message=", wrapped.Error())
}
package main
import (
"errors"
"fmt"
)
func main() {
var operation = "save"
base := errors.New("config missing")
wrapped := fmt.Errorf("%s failed: %w", operation, base)
fmt.Println("operation=", operation)
fmt.Println("base=", base.Error())
fmt.Println("has_error=", wrapped != nil)
fmt.Println("message=", wrapped.Error())
}
package main
import (
"errors"
"fmt"
)
func main() {
var operation = "delete"
base := errors.New("config missing")
wrapped := fmt.Errorf("%s failed: %w", operation, base)
fmt.Println("operation=", operation)
fmt.Println("base=", base.Error())
fmt.Println("has_error=", wrapped != nil)
fmt.Println("message=", wrapped.Error())
}
operation ← "load", base ← &errors.errorString{s:"config missing"}
8func main() {9 var operation→ "load" = "load" //@operation="save", "delete"10 base→ &errors.errorString{s:"config missing"} := errors.New("config missing")11 wrapped→ &fmt.wrapError{msg:"load failed: config missing", err:(*errors.errorString)(⟨addr A⟩)} := fmt.Errorf("%s failed: %w", operation"load", base&errors.errorString{s:"config missing"})1213 fmt.Println("operation=", operation"load")14 fmt.Println("base=", base&errors.errorString{s:"config missing"}.Error())15 fmt.Println("has_error=", wrapped&fmt.wrapError{msg:"load failed: config missing", err:(*errors.errorString)(⟨addr A⟩)} != nil)16 fmt.Println("message=", wrapped&fmt.wrapError{msg:"load failed: config missing", err:(*errors.errorString)(⟨addr A⟩)}.Error())17}outputoperation= load base= config missing has_error= true message= load failed: config missing
operation ← "save", base ← &errors.errorString{s:"config missing"}
8func main() {9 var operation→ "save" = "save"10 base→ &errors.errorString{s:"config missing"} := errors.New("config missing")11 wrapped→ &fmt.wrapError{msg:"save failed: config missing", err:(*errors.errorString)(⟨addr A⟩)} := fmt.Errorf("%s failed: %w", operation"save", base&errors.errorString{s:"config missing"})1213 fmt.Println("operation=", operation"save")14 fmt.Println("base=", base&errors.errorString{s:"config missing"}.Error())15 fmt.Println("has_error=", wrapped&fmt.wrapError{msg:"save failed: config missing", err:(*errors.errorString)(⟨addr A⟩)} != nil)16 fmt.Println("message=", wrapped&fmt.wrapError{msg:"save failed: config missing", err:(*errors.errorString)(⟨addr A⟩)}.Error())17}outputoperation= save base= config missing has_error= true message= save failed: config missing
operation ← "delete", base ← &errors.errorString{s:"config missing"}
8func main() {9 var operation→ "delete" = "delete"10 base→ &errors.errorString{s:"config missing"} := errors.New("config missing")11 wrapped→ &fmt.wrapError{msg:"delete failed: config missing", err:(*errors.errorString)(⟨addr A⟩)} := fmt.Errorf("%s failed: %w", operation"delete", base&errors.errorString{s:"config missing"})1213 fmt.Println("operation=", operation"delete")14 fmt.Println("base=", base&errors.errorString{s:"config missing"}.Error())15 fmt.Println("has_error=", wrapped&fmt.wrapError{msg:"delete failed: config missing", err:(*errors.errorString)(⟨addr A⟩)} != nil)16 fmt.Println("message=", wrapped&fmt.wrapError{msg:"delete failed: config missing", err:(*errors.errorString)(⟨addr A⟩)}.Error())17}outputoperation= delete base= config missing has_error= true message= delete failed: config missing