errors.Unwrap în Go

Erori (errors) Go 1.13

Returnează eroarea împachetată direct în err (un singur nivel), sau nil dacă err nu împachetează nimic.

Sintaxă
func Unwrap(err error) error

Ce face errors.Unwrap

errors.Unwrap(err) apelează metoda Unwrap() error a erorii, dacă o are, și returnează eroarea din interior. Erorile create cu fmt.Errorf("...: %w", e) au această metodă. Dacă err nu împachetează nimic, rezultatul este nil.

Unwrap coboară un singur nivel. În practică rar ai nevoie de el direct: errors.Is și errors.As parcurg singure tot lanțul. E util când vrei să afișezi lanțul nivel cu nivel sau când scrii propriul tip de eroare care împachetează altă eroare (îi dai o metodă Unwrap).

Parametri

Parametru Descriere
err Eroarea de despachetat.

Ce returnează

Eroarea împachetată sau nil.

Exemple

Exemplul 1: Lanțul de erori, nivel cu nivel

package main

import (
	"errors"
	"fmt"
)

func main() {
	baza := errors.New("conexiune refuzată")
	e1 := fmt.Errorf("citesc stocul: %w", baza)
	e2 := fmt.Errorf("afișez pagina produsului: %w", e1)

	for err, nivel := error(e2), 0; err != nil; err, nivel = errors.Unwrap(err), nivel+1 {
		fmt.Printf("nivel %d: %v\n", nivel, err)
	}
	fmt.Println("Unwrap pe eroarea de bază:", errors.Unwrap(baza))
}

Rezultat

nivel 0: afișez pagina produsului: citesc stocul: conexiune refuzată
nivel 1: citesc stocul: conexiune refuzată
nivel 2: conexiune refuzată
Unwrap pe eroarea de bază: <nil>

Exemplul 2: Tip propriu care împachetează o eroare

Metoda Unwrap face ca errors.Is să poată vedea eroarea din interior.

package main

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

type EroareImport struct {
	Linie int
	Err   error
}

func (e *EroareImport) Error() string { return fmt.Sprintf("linia %d: %v", e.Linie, e.Err) }
func (e *EroareImport) Unwrap() error { return e.Err }

func main() {
	_, cauza := os.Open("poze/produs-17.jpg")
	err := &EroareImport{Linie: 17, Err: cauza}

	fmt.Println(err)
	fmt.Println("Unwrap:", errors.Unwrap(err))
	fmt.Println("Fișier inexistent:", errors.Is(err, fs.ErrNotExist))
}

Rezultat

linia 17: open poze/produs-17.jpg: no such file or directory
Unwrap: open poze/produs-17.jpg: no such file or directory
Fișier inexistent: true

Greșeli frecvente

  • Faci errors.Unwrap(err) == ErrX ca să verifici o santinelă. Merge doar dacă eroarea este exact un nivel mai jos; folosește errors.Is.

Comenzi înrudite

  • errors.Is: Verifică dacă eroarea err este target sau o conține, căutând prin toate erorile împachetate cu %w sau Join.
  • 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.Join: Unește mai multe erori într-una singură; mesajele apar pe linii separate, iar errors.Is/As le găsesc pe fiecare.