Какие архитектурные анти-паттерны вы встречали в Go-проектах и как их избегать?

Ответ

Хорошая архитектура нацелена на создание поддерживаемого, тестируемого и расширяемого кода. Вот несколько распространенных анти-паттернов в Go и способы их решения:

1. Глобальные переменные и неявное состояние
Усложняют тестирование, приводят к неочевидным зависимостям и состоянию гонки в конкурентной среде.

Плохо:

var db *sql.DB // Глобальная переменная

func GetUser(id int) (*User, error) {
    // Функция неявно зависит от глобальной переменной db
    row := db.QueryRow("SELECT ...") 
    // ...
}

Как лучше:
Использовать Dependency Injection (DI). Передавать зависимости явно через параметры конструктора или функции.

type UserRepo struct {
    db *sql.DB
}

func (r *UserRepo) GetUser(id int) (*User, error) {
    row := r.db.QueryRow("SELECT ...")
    // ...
}

2. Жесткая связность компонентов (Tight Coupling)
Модули знают о конкретных реализациях друг друга, что усложняет замену компонентов и тестирование.

Плохо:

type OrderService struct {
    // Привязка к конкретной реализации MySQL
    storage *MySQLStorage 
}

Как лучше:
Следовать Принципу инверсии зависимостей (DIP). Зависеть от абстракций (интерфейсов), а не от конкретных типов.

type OrderStorage interface {
    Save(Order) error
}

type OrderService struct {
    storage OrderStorage // Зависимость от интерфейса
}

3. Нарушение принципа единственной ответственности (SRP)
Структура или пакет делают слишком много. Например, один модуль отвечает за логику, работу с БД и форматирование ответа.

Плохо:

// Генератор отчётов знает и о БД, и о форматах вывода
type ReportGenerator struct {
    db     *sql.DB
    pdfGen *PDFGenerator
    csvGen *CSVGenerator
}

Как лучше:
Разделять обязанности. Один компонент получает данные, другой — форматирует их.

4. Чрезмерное использование interface{}
Использование пустого интерфейса (any) там, где можно использовать конкретный тип или более строгий интерфейс, приводит к потере типобезопасности и усложняет код из-за постоянных проверок типа (type assertion).