Как определить конкретный тип значения, хранящегося в переменной типа `any` (interface{})?

Ответ

Для определения конкретного типа значения, которое хранится в пустом интерфейсе interface{} (или его псевдониме any), в Go есть два основных идиоматичных способа: утверждение типа (type assertion) и переключатель типов (type switch).

1. Утверждение типа (Type Assertion)

Это способ проверить, содержит ли переменная интерфейса значение определённого типа, и извлечь его. Безопасная форма возвращает два значения:

  • value: значение, приведённое к указанному типу.
  • ok: булево значение, true если преобразование успешно, и false в противном случае.

Использование формы с одним возвращаемым значением (val.(string)) вызовет панику, если тип не совпадёт.

var i interface{} = "hello"

// Безопасное утверждение типа
if s, ok := i.(string); ok {
    fmt.Printf("Значение '%s' является строкойn", s)
}

2. Переключатель типов (Type Switch)

Это наиболее удобный способ, если нужно проверить значение на соответствие нескольким разным типам.

func checkType(i any) {
    switch v := i.(type) {
    case int:
        fmt.Printf("Это целое число: %dn", v)
    case string:
        fmt.Printf("Это строка: %sn", v)
    case bool:
        fmt.Printf("Это булево значение: %tn", v)
    default:
        fmt.Printf("Неизвестный тип: %T со значением %vn", v, v)
    }
}

checkType(42)
checkType("hello")

Рефлексия (reflect): В качестве альтернативы можно использовать пакет reflect (reflect.TypeOf(i)), но это более медленный и сложный подход. Его стоит применять только в тех случаях, когда типы неизвестны на этапе компиляции.