package app import ( "log/slog" "net/http" "github.com/olezhek28/di-demo/internal/config" ) // App — структура приложения. // Содержит DI-контейнер и HTTP-сервер. // API-слой отвечает за хендлеры и роутинг, а http.Server живёт здесь — // это инфраструктура, а не бизнес-логика. type App struct { diContainer *diContainer httpServer *http.Server } // New создаёт приложение и инициализирует все зависимости через DI-контейнер. // Вся цепочка зависимостей разрешается здесь: от базы данных до HTTP-хендлеров. // Если какая-то зависимость не создалась — процесс завершится внутри контейнера. func New() *App { a := &App{ diContainer: newDIContainer(), } a.initDeps() return a } // initDeps последовательно вызывает функции инициализации. // Если нужно добавить новый шаг (миграции, метрики и т.д.) — // просто добавить функцию в слайс inits. func (a *App) initDeps() { inits := []func(){ a.initHTTPServer, } for _, fn := range inits { fn() } } // initHTTPServer создаёт HTTP-сервер. // API-слой (Handler) предоставляет только роутинг — Routes(). // А http.Server с адресом и конфигом создаётся здесь, в app-слое. func (a *App) initHTTPServer() { a.httpServer = &http.Server{ Addr: config.AppConfig().HTTPAddr, Handler: a.diContainer.Handler().Routes(), } } // Run запускает HTTP-сервер. // // Сейчас просто запускаем и всё. Перехват сигналов, graceful shutdown, // закрытие ресурсов в правильном порядке — тема отдельного видео. func (a *App) Run() error { slog.Info("сервер запущен", "addr", config.AppConfig().HTTPAddr) return a.httpServer.ListenAndServe() }