Інтерфейси в Go можуть породжувати неоднозначність щодо базового типу.
Насправді порожній інтерфейс може містити будь-яке конкретне значення взагалі (зокрема примітиви).
Твердження типу дає нам змогу витягти базове конкретне значення зі значення інтерфейсу за допомогою такого синтаксису: interfaceVariable.(concreteType).
Якщо ми присвоїмо результат цієї інструкції лише одному значенню, ми стверджуємо, що змінна інтерфейсу містить значення конкретного типу. Як наслідок, під час виконання може виникнути паніка, якщо значення інтерфейсу не має вказаного конкретного типу. Наприклад:
var input interface{} = 12
str := input.(string) // panic at runtime since input is not a string!
Ми можемо перевірити, чи містить значення інтерфейсу конкретний тип, скориставшись обома поверненими значеннями твердження типу: базовим значенням і булевим значенням (англ. Boolean), яке вказує, чи вдалося твердження. Наприклад:
str, ok := input.(string) // no panic if input is not a string
Якщо input містить string, то str буде базовим значенням, а ok - правдою.
Якщо input не містить string, то str буде нульовим значенням типу string (тобто "" - порожній рядок тексту (англ. string)), а ok буде неправдою.
Паніка не виникає за жодних обставин.
Часто можна натрапити на таку ідіому:
str, ok := input.(string)
if !ok {
str = "a default value"
}
Перемикач типів може виконати кілька тверджень типу підряд.
Він має той самий синтаксис, що й твердження типу (interfaceVariable.(concreteType)), але замість конкретного concreteType використовує ключове слово type.
Ось приклад:
var i interface{} = 12 // try: 12.3, true, int64(12), []int{}, map[string]int{}
switch v := i.(type) {
case int:
fmt.Printf("the integer %d\n", v)
case string:
fmt.Printf("the string %s\n", v)
default:
fmt.Printf("type, %T, not handled explicitly: %#v\n", v, v)
}