Ответ
Type Assertion (утверждение типа) в Go — это операция, которая позволяет проверить, содержит ли интерфейсная переменная значение конкретного типа, и если да, то извлечь это значение.
Существует две формы:
t := i.(T)
— паникует, если типi
не являетсяT
.t, ok := i.(T)
— безопасная форма. Если тип совпадает,ok
будетtrue
, аt
получит значение. Если нет,ok
будетfalse
, аt
— нулевым значением типаT
, паники не произойдет.
Основные сценарии использования:
-
Проверка и преобразование интерфейса к конкретному типу Это самый частый кейс, когда нужно безопасно работать со значением, скрытым за интерфейсом.
var val interface{} = "hello" // Безопасная проверка if str, ok := val.(string); ok { fmt.Printf("Строка найдена: %sn", str) } else { fmt.Println("Значение не является строкой") }
-
Обработка разнородных данных с помощью
type switch
Идеально подходит для функций, принимающихinterface{}
, когда нужно выполнить разную логику для разных типов.func process(i interface{}) { switch v := i.(type) { // Специальный синтаксис для switch case int: fmt.Printf("Целое число: %dn", v) case string: fmt.Printf("Строка: %sn", v) default: fmt.Printf("Неизвестный тип: %Tn", v) } }
-
Извлечение конкретного типа ошибки Позволяет проверить, является ли ошибка
error
экземпляром вашей кастомной структуры ошибки, чтобы получить доступ к дополнительным полям (например, коду ошибки).// type MyCustomError struct { ... } _, err := someFunction() if myErr, ok := err.(*MyCustomError); ok { // Здесь можно работать с полями myErr fmt.Println("Произошла кастомная ошибка с кодом:", myErr.Code) }
-
Работа с данными после десериализации (например, JSON) Когда вы десериализуете JSON в
interface{}
, вы получаетеmap[string]interface{}
. Type assertion необходим для доступа к значениям.var data interface{} json.Unmarshal([]byte(`{"name": "Gopher", "age": 10}`), &data) if m, ok := data.(map[string]interface{}); ok { if name, ok := m["name"].(string); ok { fmt.Println("Имя:", name) } }