Ce face fmt.Errorf
fmt.Errorf funcționează ca Sprintf, dar returnează o valoare de tip error în loc de text. Este modul obișnuit de a crea erori cu detalii: fmt.Errorf("nota %d nu este validă", n).
Verbul special %w (de la wrap, împachetare) pune în mesaj textul unei erori existente și o păstrează înăuntru. Așa adaugi context („la citirea fișierului note.txt: …”) fără să pierzi eroarea originală: errors.Is și errors.As o găsesc în continuare, iar errors.Unwrap o scoate. Din Go 1.20 poți folosi mai multe %w în același apel.
Cu %v în loc de %w se copiază doar textul erorii; legătura cu eroarea originală se pierde.
Parametri
| Parametru | Descriere |
|---|---|
format |
Mesajul erorii, cu verbe ca la Printf. Convenția Go: litere mici la început, fără punct la final. |
a ...any |
Valorile pentru verbe; pentru %w valoarea trebuie să fie de tip error. |
Ce returnează
O valoare error. Cu %w, eroarea are metoda Unwrap care dă eroarea împachetată.
Exemple
Exemplul 1: Eroare cu detalii
package main
import "fmt"
func verificaNota(n int) error {
if n < 1 || n > 10 {
return fmt.Errorf("nota %d nu este între 1 și 10", n)
}
return nil
}
func main() {
for _, n := range []int{9, 12, 0} {
if err := verificaNota(n); err != nil {
fmt.Println("Eroare:", err)
} else {
fmt.Println(n, "este o notă validă")
}
}
}
Rezultat
9 este o notă validă
Eroare: nota 12 nu este între 1 și 10
Eroare: nota 0 nu este între 1 și 10
Exemplul 2: Împachetare cu %w și verificare cu errors.Is
Mesajul final are tot contextul, dar errors.Is recunoaște eroarea originală ErrStocEpuizat. Cu %v legătura s-ar pierde.
package main
import (
"errors"
"fmt"
)
var ErrStocEpuizat = errors.New("stoc epuizat")
func rezerva(produs string, bucati int) error {
if bucati > 3 {
return fmt.Errorf("rezervare %s (%d buc.): %w", produs, bucati, ErrStocEpuizat)
}
return nil
}
func main() {
err := rezerva("cafea", 5)
fmt.Println(err)
fmt.Println("este ErrStocEpuizat?", errors.Is(err, ErrStocEpuizat))
fmt.Println("eroarea din interior:", errors.Unwrap(err))
copie := fmt.Errorf("rezervare: %v", ErrStocEpuizat)
fmt.Println("cu verbul v:", errors.Is(copie, ErrStocEpuizat))
}
Rezultat
rezervare cafea (5 buc.): stoc epuizat
este ErrStocEpuizat? true
eroarea din interior: stoc epuizat
cu verbul v: false
Exemplul 3: Context în jurul unei erori din biblioteca standard
errors.As scoate eroarea concretă *strconv.NumError din interior, chiar dacă a fost împachetată.
package main
import (
"errors"
"fmt"
"strconv"
)
func citesteVarsta(text string) (int, error) {
v, err := strconv.Atoi(text)
if err != nil {
return 0, fmt.Errorf("vârsta %q: %w", text, err)
}
return v, nil
}
func main() {
_, err := citesteVarsta("douăzeci")
fmt.Println(err)
var numErr *strconv.NumError
if errors.As(err, &numErr) {
fmt.Println("funcția:", numErr.Func, "| cauza:", numErr.Err)
}
}
Rezultat
vârsta "douăzeci": strconv.Atoi: parsing "douăzeci": invalid syntax
funcția: Atoi | cauza: invalid syntax
Greșeli frecvente
- Folosești
%vcând vrei să păstrezi eroarea.errors.Isva returnafalse; pentru împachetare folosește%w. - Pui
%wcu o valoare care nu esteerror.go vetsemnalează greșeala, iar la rulare apare%!w(...)în mesaj. - Scrii mesaje cu majusculă și punct („Nota invalidă.”). Erorile sunt de obicei puse una în alta („citire: conversie: nota invalidă”), deci convenția este literă mică și fără punct.
Comenzi înrudite
fmt.Printf: Afișează text formatat cu %d, %s, %.2f etc.; Sprintf returnează textul, Fprintf îl scrie într-un fișier sau alt Writer.strconv.Atoi: Atoi transformă un text în număr întreg (int) și returnează eroare dacă nu se poate; Itoa face invers.