Lecții din modul (2/5)
Tip afirmație
O aserțiune de tip extrage tipul concret dintr-o valoare de interfață.
Aveți nevoie de el atunci când aveți o interface{} (sau o interfață „înaltă”) în
mână și trebuie să o tratezi ca tipul său specific pentru a accesa câmpuri sau
metode care nu sunt prezente pe interfață.
Sintaxă
var i interface{} = "ciao"
s := i.(string) // "panic" form: panics if it's not a string
s, ok := i.(string) // "comma ok" form: ok = false if it's not a stringDouă forme, două semantice:
| Formular | Succes | Eșec |
|---|---|---|
v := i.(T) | v = valoare de tip T | panica la runtime |
v, ok := i.(T) | v=..., ok=true | v = valoarea zero a lui T, ok=false |
Forma „virgulă ok”: cea mai sigură
var i interface{} = 42
if s, ok := i.(string); ok {
fmt.Println("è stringa:", s)
} else {
fmt.Println("non è stringa, ignoro")
}ok vă permite să gestionați cazul de „tip greșit” fără panică. Este
model idiomatic în marea majoritate a cazurilor.
Afirmație la o interfață
Afirmația nu funcționează doar pe tipuri concrete, ci și pe altele interfete:
type Closer interface { Close() error }
func tryClose(x interface{}) {
if c, ok := x.(Closer); ok {
c.Close()
}
}Un model foarte comun în biblioteca standard: „dacă intrarea mea este, de asemenea
un io.Closer, apelați Închidere la sfârșit”.
Aserțiune despre indicatori vs valori
Afirmația trebuie să se potrivească EXACT tipului dinamic:
type Cat struct{}
func (c *Cat) Meow() {}
var a interface{} = &Cat{}
c1, ok := a.(*Cat) // ok = true
c2, ok := a.(Cat) // ok = false: it holds *Cat, not Cat*Cat și Cat sunt tipuri distincte pentru sistemul de tipuri.
Când să folosiți aserțiunea vs comutatorul de tip
- Doar 1 tip posibil, verificare „detectare caracteristică” (de exemplu, difuzare către o interfață opțională): aserțiune de tip cu
comma ok. - 2+ tipuri posibile, expediere peste mai multe ramuri: comutator de tip (lecția următoare).
Încearcă
Utilizați modelul virgulă ok pentru a extrage un șir din i.
Afișează indiciu
Sintaxă: `v, ok := i.(T)`.
Soluție disponibilă după 3 încercări
Tastați aserțiune la int fără virgulă ok (presupunem că i conține un int).
Afișează indiciu
Fără `ok` presupui că tipul este sigur; altfel panica.
Soluție disponibilă după 3 încercări
Ce se întâmplă cu `s := i.(string)` dacă i conține un int?
var i interface{} = 42
s := i.(string)Recapitulare
v := i.(T): panică dacă tipul dinamic ≠ T.v, ok := i.(T): model sigur, bifațiok.- Funcționează și împotriva unei alte interfețe („feature detect”).
Tși*Tsunt tipuri distincte pentru afirmație.- 1 tip → aserțiune; 2+ tipuri → comutator de tip.