Lekcje modułu (2/5)
Asercja typu
Afirmacja typu wyodrębnia konkretny typ z wartości interfejsu.
Potrzebujesz go, gdy masz interface{} (lub „wysoki” interfejs).
hand i należy go traktować jako specyficzny typ, aby uzyskać dostęp do pól lub
metody, których nie ma w interfejsie.
Składnia
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 stringDwie formy, dwie semantyki:
| Formularz | Sukces | Porażka |
|---|---|---|
| KODEF0 | v = wartość typu T | panika w czasie wykonywania |
| KODEF2 | KODEF3, KODEF4 | v = wartość zerowa T, ok=false |
Formularz „Przecinek ok”: najbezpieczniejszy
var i interface{} = 42
if s, ok := i.(string); ok {
fmt.Println("è stringa:", s)
} else {
fmt.Println("non è stringa, ignoro")
}ok pozwala bez paniki poradzić sobie z przypadkiem „złego typu”. To jest
idiomatyczny wzór w zdecydowanej większości przypadków.
Asercja do interfejsu
Twierdzenie to nie działa tylko na konkretne typy, ale także na inne interfejsy:
type Closer interface { Close() error }
func tryClose(x interface{}) {
if c, ok := x.(Closer); ok {
c.Close()
}
}Bardzo powszechny wzorzec w bibliotece standardowej: „jeśli moje dane wejściowe również to
io.Closer, wywołaj Close na końcu”.
Asercja dotycząca wskaźników a wartości
Twierdzenie musi DOKŁADNIE pasować do typu dynamicznego:
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 to różne typy systemu typów.
Kiedy używać asercji a przełącznika typu
- Tylko 1 możliwy typ, sprawdzenie „wykrywania funkcji” (np. rzutowanie na opcjonalny interfejs): twierdzenie typu z
comma ok. - 2+ możliwe typy, wysyłka przez wiele gałęzi: przełącznik typu (następna lekcja).
Spróbuj
Użyj wzorca przecinek ok, aby wyodrębnić ciąg z i.
Pokaż wskazówkę
Składnia: `v, ok := i.(T)`.
Rozwiązanie dostępne po 3 próbach
Wpisz asercję na int bez przecinka ok (załóż, że i zawiera int).
Pokaż wskazówkę
Bez `ok` zakładasz, że typ jest pewny; inaczej wpadnij w panikę.
Rozwiązanie dostępne po 3 próbach
Co się stanie z `s := i.(string)`, jeśli zawiera int?
var i interface{} = 42
s := i.(string)Podsumowanie
v := i.(T): panika, jeśli typ dynamiczny ≠ T.v, ok := i.(T): bezpieczny wzór, sprawdźok.- Działa także z innym interfejsem („wykrywanie funkcji”).
Ti*Tto różne typy asercji.- 1 typ → asercja; Ponad 2 typy → przełącznik typu.