import
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
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()
|
||||
}
|
||||
Reference in New Issue
Block a user