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

raw
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)
}
  1. 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"
  2. 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 {
  3. 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}
  4. 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
  1. 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
  1. 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"
  2. 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 {
  3. 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}
  4. 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