package main // Пример циклической зависимости в Fx. // // Граф зависимостей замкнулся в кольцо: // // NewEventBus(NotificationSender) — EventBus хочет отправлять уведомления // NewNotificationService(Users, EventSubscriber) — уведомления хотят знать email // NewUserService(Auth) — пользователи хотят проверять токен // NewAuthService(EventPublisher) — авторизация хочет публиковать события // ↑ ↓ // └──────── EventBus реализует EventPublisher ─────────┘ // // Ни один объект нельзя создать первым — каждому нужен ещё не созданный. // // Wire ловит такой цикл при кодогенерации (до запуска). // Fx ловит его в рантайме (при старте приложения). // Результат одинаковый — приложение не запустится. // // Запустите: go run ./cmd/fx-di-broken/ // Результат: ошибка "In: cannot depend on the provided type" import ( "log/slog" "go.uber.org/fx" ) // === Интерфейсы === type NotificationSender interface { Send(msg string) } type EventPublisher interface { Publish(event string) } type EventSubscriber interface { Subscribe(event string, handler func()) } type Auth interface { Validate(token string) bool } type Users interface { GetEmail(userID int) string } // === Реализации === type EventBus struct { notifications NotificationSender // ← вот она, циклическая зависимость } func NewEventBus(notifications NotificationSender) *EventBus { slog.Info("шина событий создана") return &EventBus{notifications: notifications} } func (b *EventBus) Publish(event string) {} func (b *EventBus) Subscribe(event string, handler func()) {} type AuthService struct { events EventPublisher } func NewAuthService(events EventPublisher) *AuthService { slog.Info("сервис авторизации создан") return &AuthService{events: events} } func (s *AuthService) Validate(token string) bool { return true } type UserService struct { auth Auth } func NewUserService(auth Auth) *UserService { slog.Info("сервис пользователей создан") return &UserService{auth: auth} } func (s *UserService) GetEmail(userID int) string { return "user@example.com" } type NotificationService struct { users Users events EventSubscriber } func NewNotificationService(users Users, events EventSubscriber) *NotificationService { slog.Info("сервис уведомлений создан") return &NotificationService{users: users, events: events} } func (s *NotificationService) Send(msg string) { slog.Info("уведомление отправлено", "msg", msg) } // === Fx === func main() { fx.New( fx.Provide( fx.Annotate(NewEventBus, fx.As(new(EventPublisher)), fx.As(new(EventSubscriber))), fx.Annotate(NewAuthService, fx.As(new(Auth))), fx.Annotate(NewUserService, fx.As(new(Users))), fx.Annotate(NewNotificationService, fx.As(new(NotificationSender))), ), fx.Invoke(func(pub EventPublisher) { slog.Info("всё запустилось") // сюда не дойдём }), ).Run() }