В .NET вопросы «как собрать граф зависимостей», «откуда взять настройки» и «как провалидировать модель» решает фреймворк. Host.CreateApplicationBuilder поднимает встроенный DI-контейнер, который сам разрешает граф по зарегистрированным типам; IConfiguration склеивает appsettings.json, переменные окружения и секреты в единое дерево, а IOptions<T> биндит его в типизированные классы; атрибуты [Required]/[Range] плюс DataAnnotations валидируют модели через рефлексию. Всё это — «магия» рантайма, которую вы конфигурируете, но не пишете.
В Go культура противоположна: зависимости собираются руками, конфиг приходит из переменных окружения и маппится в структуру явным вызовом, а валидация и биндинг опираются на тэги структур — обычные строки, которые библиотеки читают через рефлексию. Меньше «магии», больше видимого кода: граф зависимостей виден целиком в main(), источник каждой настройки прослеживается, а порядок инициализации детерминирован. Этот раздел переносит ваш enterprise-опыт в эту модель — показывает идиомы ручного DI (Composition Root, «accept interfaces, return structs»), философию 12-factor для конфигурации и механику тэгов/рефлексии/валидации, постоянно сверяясь с тем, как то же самое устроено в .NET.
После этого раздела вы будете:
- Собирать дерево зависимостей вручную в Composition Root, применяя constructor injection (
NewXxx(deps...) *Xxx) и правило «accept interfaces, return structs»; понимать, почему многие Go-команды сознательно обходятся без DI-контейнера. - Знать, когда оправданы инструменты DI —
google/wire(compile-time codegen) иuber-go/fx/uber-go/dig(runtime-контейнер) — и как они соотносятся сIServiceCollection. - Конфигурировать сервис по 12-factor: маппить переменные окружения в структуру с тэгами и дефолтами (
caarlos0/env,ilyakaznacheev/cleanenv), понимать местоspf13/viper, флагов и приоритет источников. - Читать и писать struct tags, понимать, как их достаёт пакет
reflect, какова цена рефлексии и почему в Go её применяют дозированно. - Валидировать структуры через
go-playground/validatorтэгамиvalidate:"..."и писать кастомные правила. - Чётко сопоставлять привычные .NET-механизмы (DI-контейнер,
IConfiguration/IOptions, атрибуты/DataAnnotations) с их Go-эквивалентами и осознанно выбирать подход.
- Внедрение зависимостей (DI) — IoC без контейнера: ручной DI, Composition Root в
main(), constructor injection, «accept interfaces, return structs», обзорwire/fx/dig. Фундамент раздела. - Конфигурация — философия
env(12-factor), маппинг env → структура, библиотекиcaarlos0/env/cleanenv/viper, флаги, приоритет источников и секреты. - Тэги структур, рефлексия, валидация — синтаксис тэгов, чтение через
reflect, цена рефлексии, валидация черезgo-playground/validatorи кастомные правила. - Сравнение с .NET — консолидированный мостик: контейнер против Composition Root,
IConfiguration/IOptionsпротив env-маппинга, атрибуты против тэгов, сводка «как делать привычное X».
| В .NET / C# | В Go | Ключевое отличие |
|---|---|---|
Встроенный DI-контейнер (IServiceCollection/ServiceProvider), авторазрешение графа |
Ручной Composition Root в main(), constructor injection |
Граф собирается явно и виден целиком; нет рефлексии и «магии» разрешения |
| Время жизни: Singleton / Scoped / Transient | Решает структура кода: один экземпляр на приложение или новый на запрос | Нет понятия «lifetime» как настройки контейнера — это просто где вы создаёте объект |
class C : IFoo + регистрация AddScoped<IFoo, C>() |
Интерфейс объявляет потребитель; реализация подставляется в main |
Интерфейсы неявные и узкие; «accept interfaces, return structs» |
IConfiguration + appsettings.json + провайдеры |
Переменные окружения + явный маппинг в структуру | 12-factor: конфиг в env, не в файлах репозитория |
IOptions<T> binding |
env.Parse(&cfg) / cleanenv.ReadEnv(&cfg) |
Биндинг — явный вызов, а не DI-сервис |
Атрибуты [Required], [Range] + DataAnnotations |
Struct tags validate:"required,..." + go-playground/validator |
Атрибуты типобезопасны; тэги — строки, ошибку в тэге компилятор не ловит ❌ |
| Source Generators / Reflection Emit | Тэги + reflect, а для горячих путей — кодогенерация (Раздел 7) |
Рефлексия применяется дозированно из-за цены на рантайме |