Модульні уроки (2/5)
Твердження типу
Затвердження типу витягує конкретний тип із значення інтерфейсу.
Вам це потрібно, якщо у вас є interface{} (або «високий» інтерфейс) у
рукою і потрібно розглядати його як певний тип для доступу до полів або
методи відсутні в інтерфейсі.
Синтаксис
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 stringДві форми, дві семантики:
| Форма | Успіх | Відмова |
|---|---|---|
v := i.(T) | v = значення типу T | паніка під час виконання |
v, ok := i.(T) | v=..., ok=true | v = нульове значення T, ok=false |
Форма «Comma ok»: найбезпечніша
var i interface{} = 42
if s, ok := i.(string); ok {
fmt.Println("è stringa:", s)
} else {
fmt.Println("non è stringa, ignoro")
}ok дозволяє без паніки впоратися зі справою «неправильного типу». Це
ідіоматичний зразок у переважній більшості випадків.
Твердження до інтерфейсу
Твердження працює не тільки на конкретних типах, а й на інших інтерфейси:
type Closer interface { Close() error }
func tryClose(x interface{}) {
if c, ok := x.(Closer); ok {
c.Close()
}
}Дуже поширений шаблон у стандартній бібліотеці: «якщо мій вхід також
io.Closer, виклик Close в кінці».
Твердження про покажчики проти значень
Твердження має ТОЧНО відповідати динамічному типу:
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 та Cat є різними типами для системи типів.
Коли використовувати перемикач твердження проти типу
- Лише 1 можливий тип, перевірка «виявлення функції» (наприклад, переведення до додаткового інтерфейсу): затвердження типу з
comma ok. - 2+ можливі типи, розсилка по кількох гілках: перемикач типів (наступний урок).
Спробуйте
Використовуйте шаблон коми ok, щоб витягнути рядок із i.
Показати підказку
Синтаксис: `v, ok := i.(T)`.
Рішення доступне після 3 спроб
Введіть твердження для int без коми ok (припустімо, що i містить int).
Показати підказку
Без `ok` ви припускаєте, що тип певний; інакше паніка.
Рішення доступне після 3 спроб
Що станеться з `s := i.(рядок)`, якщо i містить int?
var i interface{} = 42
s := i.(string)Підведення підсумків
v := i.(T): паніка, якщо динамічний тип ≠ T.v, ok := i.(T): безпечний шаблон, перевіртеok.- Працює також з іншим інтерфейсом ("виявлення функції").
Tта*Tє різними типами для твердження.- 1 вид → твердження; 2+ типу → перемикач типу.