Error Wrapping and Inspection
Errors As
errors.As extracts a typed error from a wrapped error chain.
errors as
Use `errors.As` when a caller needs details from a specific error type rather than just a yes-or-no match.
Errors As
errors_as.go
Replay: real traced execution (multi-file project)
package main
import (
"errors"
"fmt"
"strconv"
)
func main() {
var raw = "12x"
_, parseErr := strconv.Atoi(raw)
var numberErr *strconv.NumError
matched := false
function := "none"
value := "none"
if parseErr != nil {
err := fmt.Errorf("parse count: %w", parseErr)
matched = errors.As(err, &numberErr)
if numberErr != nil {
function = numberErr.Func
value = numberErr.Num
}
}
fmt.Println("raw=", raw)
fmt.Println("matched=", matched)
fmt.Println("function=", function)
fmt.Println("value=", value)
}
package main
import (
"errors"
"fmt"
"strconv"
)
func main() {
var raw = "34"
_, parseErr := strconv.Atoi(raw)
var numberErr *strconv.NumError
matched := false
function := "none"
value := "none"
if parseErr != nil {
err := fmt.Errorf("parse count: %w", parseErr)
matched = errors.As(err, &numberErr)
if numberErr != nil {
function = numberErr.Func
value = numberErr.Num
}
}
fmt.Println("raw=", raw)
fmt.Println("matched=", matched)
fmt.Println("function=", function)
fmt.Println("value=", value)
}
package main
import (
"errors"
"fmt"
"strconv"
)
func main() {
var raw = "go"
_, parseErr := strconv.Atoi(raw)
var numberErr *strconv.NumError
matched := false
function := "none"
value := "none"
if parseErr != nil {
err := fmt.Errorf("parse count: %w", parseErr)
matched = errors.As(err, &numberErr)
if numberErr != nil {
function = numberErr.Func
value = numberErr.Num
}
}
fmt.Println("raw=", raw)
fmt.Println("matched=", matched)
fmt.Println("function=", function)
fmt.Println("value=", value)
}
raw ← "12x", parseErr ← &strconv.NumError{Func:"Atoi", Num:"12x", Err:(*errors.errorString)(⟨addr A⟩)}
9func main() {10 var raw→ "12x" = "12x" //@raw="34", "go"11 _, parseErr→ &strconv.NumError{Func:"Atoi", Num:"12x", Err:(*errors.errorString)(⟨addr A⟩)} := strconv.Atoi(raw"12x")12 var numberErr→ (*strconv.NumError)(nil) *strconv.NumError13 matched→ false := false14 function→ "none" := "none"15 value→ "none" := "none"err ← &fmt.wrapError{msg:"parse count: strconv.Atoi: parsing \"12x\": invalid syntax", err:(*strconv.NumError)(⟨addr B⟩)}
17if parseErr&strconv.NumError{Func:"Atoi", Num:"12x", Err:(*errors.errorString)(⟨addr A⟩)} != nil {18 err→ &fmt.wrapError{msg:"parse count: strconv.Atoi: parsing \"12x\": invalid syntax", err:(*strconv.NumError)(⟨addr B⟩)} := fmt.Errorf("parse count: %w", parseErr&strconv.NumError{Func:"Atoi", Num:"12x", Err:(*errors.errorString)(⟨addr A⟩)})19 matched→ true = errors.As(err&fmt.wrapError{msg:"parse count: strconv.Atoi: parsing \"12x\": invalid syntax", err:(*strconv.NumError)(⟨addr B⟩)}, &numberErr→ &strconv.NumError{Func:"Atoi", Num:"12x", Err:(*errors.errorString)(⟨addr A⟩)})20 if numberErr != nil {function ← "Atoi", value ← "12x"
19matched = errors.As(err, &numberErr)20if numberErr&strconv.NumError{Func:"Atoi", Num:"12x", Err:(*errors.errorString)(⟨addr A⟩)} != nil {21 function→ "Atoi" = numberErr.Func"Atoi"22 value→ "12x" = numberErr.Num"12x"23}fmt.Println("raw=", raw)
26 fmt.Println("raw=", raw"12x")27 fmt.Println("matched=", matchedtrue)28 fmt.Println("function=", function"Atoi")29 fmt.Println("value=", value"12x")30}outputraw= 12x matched= true function= Atoi value= 12x
raw ← "34", parseErr ← <nil>, numberErr ← (*strconv.NumError)(nil)
9func main() {10 var raw→ "34" = "34"11 _, parseErr→ <nil> := strconv.Atoi(raw"34")12 var numberErr→ (*strconv.NumError)(nil) *strconv.NumError13 matched→ false := false14 function→ "none" := "none"15 value→ "none" := "none"1617 if parseErr != nil {18 err := fmt.Errorf("parse count: %w", parseErr)19 matched = errors.As(err, &numberErr)20 if numberErr != nil {21 function = numberErr.Func22 value = numberErr.Num23 }24 }2526 fmt.Println("raw=", raw"34")27 fmt.Println("matched=", matchedfalse)28 fmt.Println("function=", function"none")29 fmt.Println("value=", value"none")30}outputraw= 34 matched= false function= none value= none
raw ← "go", parseErr ← &strconv.NumError{Func:"Atoi", Num:"go", Err:(*errors.errorString)(⟨addr A⟩)}
9func main() {10 var raw→ "go" = "go"11 _, parseErr→ &strconv.NumError{Func:"Atoi", Num:"go", Err:(*errors.errorString)(⟨addr A⟩)} := strconv.Atoi(raw"go")12 var numberErr→ (*strconv.NumError)(nil) *strconv.NumError13 matched→ false := false14 function→ "none" := "none"15 value→ "none" := "none"err ← &fmt.wrapError{msg:"parse count: strconv.Atoi: parsing \"go\": invalid syntax", err:(*strconv.NumError)(⟨addr B⟩)}
17if parseErr&strconv.NumError{Func:"Atoi", Num:"go", Err:(*errors.errorString)(⟨addr A⟩)} != nil {18 err→ &fmt.wrapError{msg:"parse count: strconv.Atoi: parsing \"go\": invalid syntax", err:(*strconv.NumError)(⟨addr B⟩)} := fmt.Errorf("parse count: %w", parseErr&strconv.NumError{Func:"Atoi", Num:"go", Err:(*errors.errorString)(⟨addr A⟩)})19 matched→ true = errors.As(err&fmt.wrapError{msg:"parse count: strconv.Atoi: parsing \"go\": invalid syntax", err:(*strconv.NumError)(⟨addr B⟩)}, &numberErr→ &strconv.NumError{Func:"Atoi", Num:"go", Err:(*errors.errorString)(⟨addr A⟩)})20 if numberErr != nil {function ← "Atoi", value ← "go"
19matched = errors.As(err, &numberErr)20if numberErr&strconv.NumError{Func:"Atoi", Num:"go", Err:(*errors.errorString)(⟨addr A⟩)} != nil {21 function→ "Atoi" = numberErr.Func"Atoi"22 value→ "go" = numberErr.Num"go"23}fmt.Println("raw=", raw)
26 fmt.Println("raw=", raw"go")27 fmt.Println("matched=", matchedtrue)28 fmt.Println("function=", function"Atoi")29 fmt.Println("value=", value"go")30}outputraw= go matched= true function= Atoi value= go