Ce face type assertion
O valoare de tip interfață (de exemplu any sau error) ascunde tipul concret. x.(T) verifică la rulare dacă x ține o valoare de tipul T și o returnează ca T. Dacă T este tot o interfață, verifică dacă valoarea are metodele ei.
Forma cu o singură valoare oprește programul cu panic dacă tipul nu se potrivește. Forma cu două valori, v, ok := x.(T), nu dă panic: ok este false, iar v primește valoarea zero a lui T. Folosește forma cu ok ori de câte ori nu ești sigur.
Pentru mai multe tipuri posibile, un type switch este mai clar decât o serie de assertion-uri. Pentru erori, errors.As este preferat lui err.(*TipEroare), pentru că verifică și erorile împachetate.
Exemple
Exemplul 1: Forma sigură, cu ok
package main
import "fmt"
func main() {
var valori = []any{42, "Iași", 3.14, true}
for _, v := range valori {
if s, ok := v.(string); ok {
fmt.Printf("text de %d octeți: %s\n", len(s), s)
} else if n, ok := v.(int); ok {
fmt.Println("întreg, dublul este", n*2)
} else {
fmt.Printf("alt tip: %T\n", v)
}
}
}
Rezultat
întreg, dublul este 84
text de 5 octeți: Iași
alt tip: float64
alt tip: bool
Exemplul 2: Verificarea unei interfețe opționale
Verificăm dacă valoarea are și metoda Reducere.
package main
import "fmt"
type Produs interface{ Pret() float64 }
type CuReducere interface{ Reducere() float64 }
type Carte struct{}
type Telefon struct{}
func (Carte) Pret() float64 { return 50 }
func (Telefon) Pret() float64 { return 2000 }
func (Telefon) Reducere() float64 { return 0.15 }
func main() {
for _, p := range []Produs{Carte{}, Telefon{}} {
pret := p.Pret()
if r, ok := p.(CuReducere); ok {
pret *= 1 - r.Reducere()
}
fmt.Printf("%T: %.2f lei\n", p, pret)
}
}
Rezultat
main.Carte: 50.00 lei
main.Telefon: 1700.00 lei
Exemplul 3: Forma fără ok dă panic
Panic-ul este oprit cu recover doar ca să putem afișa mesajul.
package main
import "fmt"
func main() {
defer func() {
fmt.Println("panic:", recover())
}()
var x any = "text"
n := x.(int)
fmt.Println(n)
}
Rezultat
panic: interface conversion: interface {} is string, not int
Greșeli frecvente
x.(T)fărăokpe date venite din exterior (JSON decodat înany): un tip neașteptat oprește programul.- Assertion pe o variabilă care nu este interfață:
invalid operation: n (variable of type int) is not an interface. - Numerele din JSON decodat în
anysuntfloat64, nuint:v.(int)eșuează.
Comenzi înrudite
type switch: Un switch care alege ramura după tipul concret ținut de o interfață, cu variabila deja convertită.interface și interfețe: Interfața descrie un set de metode; orice tip care le are o implementează automat, fără declarație explicită.any: Alias pentru interface{}: un tip care poate ține orice valoare; folosit și drept constrângere în generics.erori (error): În Go erorile sunt valori: funcțiile returnează un error, iar apelantul verifică if err != nil.