Рефлексия в Go
См. также: Справочник по Go · Важные интерфейсы · Особенности языка.
Что такое рефлексия
Рефлексия — анализ и изменение типов и значений во время выполнения через пакет reflect. В Go типы известны компилятору; рефлексия нужна, когда тип заранее не фиксирован (универсальный декодер, ORM, валидатор по тегам).
Два базовых типа:
reflect.Type— описание типа (поля структуры, kind);reflect.Value— конкретное значение, возможность чтения/записи (если addressable).
v := reflect.ValueOf(&user).Elem() // указатель → значение для записи в поля
t := v.Type()
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
tag := f.Tag.Get("json")
_ = tag
}
Type assertion и reflect
Если известен конечный набор типов — предпочтительнее утверждение типа:
switch x := v.(type) {
case int:
fmt.Println(x * 2)
case string:
fmt.Println(len(x))
default:
fmt.Println("неизвестный тип")
}
reflect оправдан при произвольных any / map[string]any / динамическом JSON без целевой структуры. С Go 1.18+ многие «обобщённые» задачи решают дженериками без рефлексии.
Теги структур
Теги — метаданные полей для инструментов и библиотек:
type User struct {
ID int `json:"id" db:"user_id"`
Name string `json:"name,omitempty"`
}
Компилятор теги игнорирует. encoding/json читает json через рефлексию (или codegen в обход). Правила:
- ключ
omitempty— пропуск нулевых значений в JSON; - имя в теге переопределяет имя поля в выводе.
Кастомная сериализация без рефлексии на горячем пути:
func (u User) MarshalJSON() ([]byte, error) { /* ... */ }
Изменение значений
Запись в поле через рефлексию возможна только если:
- передан указатель в
ValueOf; - вызван
Elem(); - поле экспортируемое (с заглавной буквы).
Иначе CanSet() вернёт false. Это защита инкапсуляции на уровне runtime.
Создание значений
t := reflect.TypeOf(MyStruct{})
ptr := reflect.New(t) // *MyStruct
slice := reflect.MakeSlice(reflect.SliceOf(t), 0, 10)
Используют в фреймворках DI, мапперах, тестовых фабриках.
Стоимость и риски
| Минус | Следствие |
|---|---|
| Медленнее прямого кода | Не в hot path |
| Нет проверки на этапе компиляции | Ошибки в рантайме |
| Сложность отладки | Паники при неверном Kind |
Рекомендации сообщества: «рефлексия — последний инструмент». Предпочитать:
- явные типы и интерфейсы;
- кодогенерацию (
go generate,stringer,sqlc,ent); - дженерики для контейнеров и алгоритмов.
Где рефлексия неизбежна
encoding/json,xml,yamlпо умолчанию;- валидация
validateпо тегам; - часть ORM (GORM) — с оговоркой по производительности;
- плагины и registry по имени типа.
Для API и микросервисов чаще выбирают явные DTO и генерацию кода (работа с БД).
Проверка интерфейса на этапе компиляции
Без рефлексии убеждаются, что тип реализует интерфейс:
var _ io.Reader = (*MyType)(nil)
Если методов не хватает — ошибка компиляции, а не сюрприз в runtime.
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Основы языка Go - философия простоты, модель компиляции и идиоматичный подход к системной разработке. Go — это статически типизированный язык программирования общего назначения, разработанный компанией Google для создания эффективных, масштабируемых и надежных систем. Набор советов, правил, принципов и обычаев в разработке на этом языке. История Go - инженерные цели языка, философия простоты и эволюция инструментов экосистемы. Экосистема приложений на Go - встроенные инструменты, workflow разработки и практики сопровождения проектов. Кавычки, rune и string, точка, запятая, автоматическая вставка точки с запятой, скобки, подчёркивания и типичные ошибки новичков в Go. Предопределённые идентификаторы не являются ключевыми словами, но имеют специальное значение в языке. Их можно переопределить в локальной области видимости, но делать это не рекомендуется. Набор функций, которые включены в стандартную библиотеку языка. Особенности Go - интерфейсы, композиция, модель ошибок и практики написания поддерживаемого кода. Go вводит конкурентность через встроенные синтаксические конструкции и правила выполнения. Ниже рассматриваются основные направления практического применения Go, объяснённые через призму его технических характеристик и требований реальных инфраструктур. Типизация, набор правил определения типа данных значений языка.Основы языка Go
Что требуется знать перед началом изучения языка программирования Go
Рекомендации по разработке на Go
История языка Go
Экосистема приложений на Go
Синтаксис и пунктуация в Go
Ключевые слова языка Go
Встроенные функции и пакеты Go
Особенности языка Go
Синтаксические конструкции Go
Области применения Go
Типы данных и объявление переменных в Go