errors.As în Go

Erori (errors) Go 1.13

Caută în lanțul de erori prima eroare de un anumit tip și o pune în target (un pointer), ca să-i citești câmpurile.

Sintaxă
func As(err error, target any) bool

Ce face errors.As

Unele erori sunt structuri cu informații: *fs.PathError are câmpul Path, o eroare de validare proprie poate avea Camp și Motiv. errors.As(err, &tinta) parcurge lanțul de erori (inclusiv cele împachetate cu %w), găsește prima eroare care are tipul lui tinta, o copiază în tinta și returnează true.

target trebuie să fie un pointer la o variabilă de tipul căutat: dacă cauți *EroareValidare, declari var ev *EroareValidare și dai &ev. Dacă dai altceva, As se oprește cu panică. Din Go 1.26 există și varianta generică errors.AsType, mai scurtă și verificată la compilare.

Parametri

Parametru Descriere
err Eroarea primită.
target Pointer la o variabilă de tipul de eroare căutat (sau de un tip interfață).

Ce returnează

true dacă a găsit o eroare potrivită (și a scris-o în target).

Exemple

Exemplul 1: Eroare de validare cu câmpuri

package main

import (
	"errors"
	"fmt"
)

type EroareValidare struct {
	Camp, Motiv string
}

func (e *EroareValidare) Error() string {
	return e.Camp + ": " + e.Motiv
}

func inregistreaza(email string, varsta int) error {
	if varsta < 18 {
		return fmt.Errorf("înregistrare %s: %w", email, &EroareValidare{"vârsta", "trebuie să ai cel puțin 18 ani"})
	}
	return nil
}

func main() {
	err := inregistreaza("ana@example.ro", 16)
	fmt.Println("Eroare:", err)

	var ev *EroareValidare
	if errors.As(err, &ev) {
		fmt.Println("Câmpul greșit:", ev.Camp)
		fmt.Println("Mesaj pentru formular:", ev.Motiv)
	}
}

Rezultat

Eroare: înregistrare ana@example.ro: vârsta: trebuie să ai cel puțin 18 ani
Câmpul greșit: vârsta
Mesaj pentru formular: trebuie să ai cel puțin 18 ani

Exemplul 2: Calea fișierului din *fs.PathError

package main

import (
	"errors"
	"fmt"
	"io/fs"
	"os"
)

func main() {
	_, err := os.Open("rapoarte/octombrie.csv")
	var pe *fs.PathError
	if errors.As(err, &pe) {
		fmt.Println("Operația:", pe.Op)
		fmt.Println("Calea:   ", pe.Path)
		fmt.Println("Cauza:   ", pe.Err)
	}
}

Rezultat

Operația: open
Calea:    rapoarte/octombrie.csv
Cauza:    no such file or directory

Greșeli frecvente

  • Dai variabila în loc de adresa ei: errors.As(err, ev). Trebuie &ev; altfel programul se oprește cu panică (și go vet te avertizează).
  • Declari ținta cu tipul greșit: dacă metoda Error are receptor pointer, eroarea este *EroareValidare, iar o țintă EroareValidare (fără steluță) nu se potrivește niciodată.

Comenzi înrudite

  • errors.AsType: Varianta generică a lui errors.As: returnează direct prima eroare de tipul E din lanț și true dacă a găsit-o.
  • errors.Is: Verifică dacă eroarea err este target sau o conține, căutând prin toate erorile împachetate cu %w sau Join.
  • errors.Unwrap: Returnează eroarea împachetată direct în err (un singur nivel), sau nil dacă err nu împachetează nimic.