В языке Go реализована статическая строгая типизация. Это значит, что тип каждой переменной известен во время компиляции, и компилятор не позволяет выполнять операции с несовместимыми типами.
Есть два вида преобразования типов:
Пример явного преобразования:
var i int = 42 var f float64 = float64(i)
Пример type assertion:
var i interface{} = "hello" s, ok := i.(string) if ok { fmt.Println("String value:", s) } else { fmt.Println("i is not a string") }
Приведение возможно только между совместимыми базовыми типами (int → float64, rune → int32, но string → int — невозможно).
Может ли interface{} хранить nil-значение, и как корректно проверить, что в переменной типа интерфейс действительно nil?
Обычная ловушка — сравнивать интерфейс, содержащий nil-значение, с nil напрямую:
var err error = nil var i interface{} = err fmt.Println(i == nil) // Ожидают true, но будет false!
Правильный способ:
Проверять, что и сам интерфейс nil, и вложенное значение nil:
if i == nil || reflect.ValueOf(i).IsNil() { fmt.Println("i действительно nil") }
История
В проекте бэкенда разработчик пытался обрабатывать различные ошибки через interface{}, сравнивал их с nil. В результате, ошибку не удавалось корректно детектировать — возникали скрытые баги и неправильная логика возврата ошибок клиенту.
История
Миграция между float64 и int без явного cast вызывала silent data loss: значения округлялись или перекидывались некорректно, так как компилятор Go требует явного преобразования для подобных операций.
История
В десериализации интерфейсных значений при работе с map[string]interface{} (например, из JSON) неожиданные типы numbers (float64), приводили к панике при использовании type assertion без дополнительной проверки ok — сервис падал из-за runtime error.