errors.Is în Go

Erori (errors) Go 1.13

Verifică dacă eroarea err este target sau o conține, căutând prin toate erorile împachetate cu %w sau Join.

Sintaxă
func Is(err, target error) bool

Ce face errors.Is

Erorile sunt adesea împachetate pe drum: fmt.Errorf("salvez comanda: %w", err) adaugă context, dar eroarea originală rămâne în interior. errors.Is(err, target) verifică eroarea err, apoi pe cea împachetată în ea, și tot așa, până găsește una egală cu target.

Se folosește pentru erori-santinelă: errors.Is(err, os.ErrNotExist), errors.Is(err, context.DeadlineExceeded), errors.Is(err, io.EOF) sau santinelele tale. Este înlocuitorul corect pentru err == target, care nu vede prin împachetare.

Un tip de eroare poate defini o metodă Is(error) bool ca să spună singur cu ce erori se consideră egal.

Parametri

Parametru Descriere
err Eroarea primită (poate fi nil; atunci rezultatul este false, cu excepția target == nil).
target Eroarea căutată, de obicei o santinelă.

Ce returnează

true dacă target se află în lanțul (arborele) de erori.

Exemple

Exemplul 1: Eroare împachetată de două ori

== nu mai recunoaște eroarea după împachetare, errors.Is da.

package main

import (
	"errors"
	"fmt"
)

var ErrNegasit = errors.New("înregistrare negăsită")

func cautaClient(id int) error {
	return fmt.Errorf("clientul %d: %w", id, ErrNegasit)
}

func trimiteFactura(id int) error {
	if err := cautaClient(id); err != nil {
		return fmt.Errorf("trimit factura: %w", err)
	}
	return nil
}

func main() {
	err := trimiteFactura(42)
	fmt.Println("Mesaj:", err)
	fmt.Println("err == ErrNegasit:        ", err == ErrNegasit)
	fmt.Println("errors.Is(err, ErrNegasit):", errors.Is(err, ErrNegasit))
}

Rezultat

Mesaj: trimit factura: clientul 42: înregistrare negăsită
err == ErrNegasit:         false
errors.Is(err, ErrNegasit): true

Exemplul 2: Fișier inexistent

Erorile pachetului os se recunosc cu santinelele fs.ErrNotExist (sau os.ErrNotExist).

package main

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

func main() {
	_, err := os.ReadFile("setari.json")
	if errors.Is(err, fs.ErrNotExist) {
		fmt.Println("Fișierul nu există, folosesc setările implicite")
	}
	fmt.Println("Eroarea completă:", err)
}

Rezultat

Fișierul nu există, folosesc setările implicite
Eroarea completă: open setari.json: no such file or directory

Greșeli frecvente

  • Împachetezi cu %v în loc de %w în fmt.Errorf. Cu %v se păstrează doar textul, iar errors.Is nu mai găsește eroarea.
  • Folosești errors.Is pentru a verifica un tip de eroare (de exemplu *fs.PathError). Pentru tipuri folosește errors.As sau errors.AsType.

Comenzi înrudite

  • errors.As: 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.
  • errors.New: Creează o eroare simplă cu mesajul dat; folosită și pentru erori-santinelă (var ErrX = errors.New(…)).
  • errors.Unwrap: Returnează eroarea împachetată direct în err (un singur nivel), sau nil dacă err nu împachetează nimic.
  • errors.Join: Unește mai multe erori într-una singură; mesajele apar pe linii separate, iar errors.Is/As le găsesc pe fiecare.