Перейти до основного вмісту
Модуль 6 · Урок 2 із 527/50 у курсі~10 min
Модульні уроки (2/5)

Твердження типу

Затвердження типу витягує конкретний тип із значення інтерфейсу. Вам це потрібно, якщо у вас є interface{} (або «високий» інтерфейс) у рукою і потрібно розглядати його як певний тип для доступу до полів або методи відсутні в інтерфейсі.

Синтаксис

Go
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=truev = нульове значення T, ok=false

Форма «Comma ok»: найбезпечніша

Go
var i interface{} = 42

if s, ok := i.(string); ok {
    fmt.Println("è stringa:", s)
} else {
    fmt.Println("non è stringa, ignoro")
}

ok дозволяє без паніки впоратися зі справою «неправильного типу». Це ідіоматичний зразок у переважній більшості випадків.

Твердження до інтерфейсу

Твердження працює не тільки на конкретних типах, а й на інших інтерфейси:

Go
type Closer interface { Close() error }

func tryClose(x interface{}) {
    if c, ok := x.(Closer); ok {
        c.Close()
    }
}

Дуже поширений шаблон у стандартній бібліотеці: «якщо мій вхід також io.Closer, виклик Close в кінці».

Твердження про покажчики проти значень

Твердження має ТОЧНО відповідати динамічному типу:

Go
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+ можливі типи, розсилка по кількох гілках: перемикач типів (наступний урок).

Спробуйте

вправи#go.m6.l2.e1
Спроби: 0Завантаження…

Використовуйте шаблон коми ok, щоб витягнути рядок із i.

Завантаження редактора…
Показати підказку

Синтаксис: `v, ok := i.(T)`.

Рішення доступне після 3 спроб

вправи#go.m6.l2.e2
Спроби: 0Завантаження…

Введіть твердження для int без коми ok (припустімо, що i містить int).

Завантаження редактора…
Показати підказку

Без `ok` ви припускаєте, що тип певний; інакше паніка.

Рішення доступне після 3 спроб

Quiz#go.m6.l2.e3
Готовий

Що станеться з `s := i.(рядок)`, якщо i містить int?

Go
var i interface{} = 42
s := i.(string)
Варіанти відповідей

Підведення підсумків

  • v := i.(T): паніка, якщо динамічний тип ≠ T.
  • v, ok := i.(T): безпечний шаблон, перевірте ok.
  • Працює також з іншим інтерфейсом ("виявлення функції").
  • T та *T є різними типами для твердження.
  • 1 вид → твердження; 2+ типу → перемикач типу.