Skip to content

Latest commit

 

History

History
42 lines (30 loc) · 6.75 KB

File metadata and controls

42 lines (30 loc) · 6.75 KB

Раздел 7. Кодогенерация как философия языка

В .NET, когда нужно избавиться от рукописного boilerplate, у вас есть богатый арсенал: рефлексия в рантайме, динамическая генерация IL (Reflection.Emit, System.Linq.Expressions), динамические прокси (Castle DynamicProxy) и — в современном мире — Source Generators, встроенные прямо в компилятор Roslyn. Значительная часть этой «магии» происходит в рантайме: сериализаторы изучают типы рефлексией, DI-контейнеры строят фабрики на лету, ORM генерируют прокси.

Go подходит к той же задаче — «как не писать руками повторяющийся код» — принципиально иначе. Идиоматичный Go избегает рантайм-магии и предпочитает кодогенерацию на этапе разработки: внешний инструмент порождает обычные .go-файлы, которые вы коммитите в репозиторий, читаете глазами и отлаживаете как любой другой код. Рефлексия в Go есть (reflect, и на ней стоят encoding/json и валидаторы из Разделов 5–6), но к ней относятся как к инструменту с ценником: за гибкость платят производительностью и потерей типобезопасности, поэтому в перформансном коде её стараются вытеснить генерацией.

Этот раздел — про философский водораздел: compile-time/dev-time генерация явного кода против runtime-рефлексии. Он короче остальных: три содержательные главы. Сначала разберём мотивацию (почему Go выбирает генерацию), затем механику (go:generate и экосистема инструментов), и в конце — детальное сравнение с миром .NET (Source Generators и Reflection.Emit).

Цели обучения

  • Понять, почему Go предпочитает кодогенерацию рефлексии: производительность, типобезопасность, читаемость и отладка, явность вместо магии.
  • Знать, где рефлексия в Go всё же используется (encoding/json, валидаторы) и почему её избегают на горячем пути.
  • Освоить директиву //go:generate и понять, что Go лишь оркеструет внешние инструменты, а не генерирует код сам.
  • Познакомиться с ключевыми инструментами экосистемы: stringer, mockery, protoc, sqlc, и со «смежной» compile-time фичей go:embed.
  • Уметь устанавливать инструменты (go install, директива tool в go.mod начиная с Go 1.24).
  • Чётко разграничить подход Go и C# Source Generators / Reflection.Emit: что выполняется в рантайме, а что на этапе компиляции, и почему механика разная при схожей мотивации.

Содержание раздела

  1. Философия: генерация (compile-time) vs рефлексия (runtime) — почему Go выбирает явный сгенерированный код вместо рантайм-магии; где рефлексия всё же живёт и какова её цена.
  2. go:generate и инструменты — директива //go:generate, команда go generate, экосистема (stringer, mockery, protoc, sqlc), установка инструментов и сквозной пример.
  3. Сравнение с .NET — C# Source Generators (Roslyn) и Reflection.Emit против внешних генераторов Go; где что выполняется, сводная таблица и общий тренд к compile-time.

Ориентир: что в .NET → что в Go

Держите таблицу под рукой при чтении раздела. Детали каждого сопоставления — в соответствующих главах.

Механизм в .NET Когда работает Аналог/ответ в Go
Рефлексия (System.Reflection) runtime пакет reflect — есть, но избегается в горячем пути
Reflection.Emit / DynamicMethod (генерация IL) runtime отсутствует в идиоматичном Go; вместо этого — генерация кода до сборки
System.Linq.Expressions (компиляция деревьев) runtime нет прямого аналога; те же задачи решают кодогенерацией
Динамические прокси (Castle DynamicProxy) runtime сгенерированные моки (mockery) — на этапе разработки
Source Generators (Roslyn) compile-time, в компиляторе внешние генераторы + go generate — отдельный шаг, плоский текст
T4-шаблоны (Text Templates) dev-time / build go:generate + шаблонные генераторы (text/template)
Сериализация через рефлексию (JsonSerializer по умолчанию) runtime encoding/json (тоже рефлексия) или генераторы (easyjson и др.)
System.Text.Json source-gen контекст compile-time генераторы маршалинга (тот же мотив — убрать рефлексию)
Встраивание ресурсов (EmbeddedResource + Assembly.GetManifestResourceStream) build + runtime //go:embed — встраивание файлов на этапе компиляции

⌂ Главная · → Следующий: Генерация vs рефлексия