Архитектура · 0.8.1

Go backend: слои и путь запроса

Пакеты, интерфейсы и путь Create-запроса.

На этой странице

ENTITY_NAME в пути — placeholder каталога вашей сущности, например product для Product; EntityName — её тип в коде. Подставьте фактические имена своего проекта. Примеры Article ниже показывают отдельную сущность, а не обязательный модуль любого приложения.

HTTP и PostgreSQL находятся во внешних адаптерах. Прикладной сервис Article работает с интерфейсом Repository, а не с конкретным драйвером БД. Реализации подключаются при сборке приложения в bootstrap.

Custom-hooks входят в тот же сценарий через объявленные интерфейсы. Поэтому типовую обработку можно обновлять генерацией, а собственные проверки и действия — развивать в custom-коде.

За что отвечает каждый пакет

Пакет Ответственность
domain Типы сущностей и общие ошибки. Не импортирует HTTP и PostgreSQL.
app/ENTITY_NAME Команды, запросы и сценарии Article. Объявляет интерфейсы Repository и Hooks.
adapters HTTP-обработчики и PostgreSQL-репозиторий с pgx и явным SQL.
infrastructure Подключение к БД, миграции и технические механизмы.
generated/bootstrap Сборка конфигурации, репозитория, сервиса, hooks и HTTP-обработчиков.

Дерево показывает основные пути на примере Article, а не полный список файлов. Набор файлов зависит от модели и возможностей проекта.

backend/ · пример Article с CRUD

cmd/api/main.go
internal/
├── domain/
│   └── article.go
├── app/
│   ├── article/
│   │   ├── commands.go
│   │   ├── queries.go
│   │   └── service.go
│   └── listquery/query.go
├── adapters/
│   ├── http/generated/
│   │   ├── article_handler.go
│   │   ├── article_mapper.go
│   │   └── article_routes.go
│   └── postgres/generated/
│       ├── article_repository.go
│       └── ENTITY_NAME_queries.sql
├── infrastructure/
│   ├── database/database.go
│   └── migrations/migrations.go
├── generated/
│   ├── bootstrap/app.go
│   ├── config/config.go
│   ├── registry/entities.go
│   └── customcontracts/composition.go
└── custom/
    ├── app/
    │   ├── composition.go
    │   └── routes.go
    └── ENTITY_NAME/hooks.go

domain — типы сущностей и ошибки

Здесь определены типы сущностей и общие ошибки. Пакет не импортирует HTTP и PostgreSQL: формат запроса преобразует HTTP-mapper, строки БД — адаптер хранения. Файлы моделей остаются под управлением генератора, хотя в их пути нет слова generated.

app — сценарии и их интерфейсы

В ENTITY_NAME/service.go объявлены Repository, Hooks и Service. Команды и запросы задают входные данные сценариев. Интерфейсы находятся в том пакете, который их использует: сервис определяет, какие операции ему нужны от хранилища и custom-расширений.

adapters — HTTP и PostgreSQL

HTTP-обработчик принимает запрос, вызывает прикладной сервис и формирует ответ. PostgreSQL-репозиторий реализует интерфейс Repository с помощью pgx и явного SQL. Во время выполнения сервис вызывает репозиторий через интерфейс; в исходниках адаптер зависит от контракта app, а не наоборот.

infrastructure — технические механизмы

Подключение к БД, запуск миграций и хранение файлов при включённой media-функциональности отделены от обработки Article. Так настройка соединений и хранилищ не смешивается с логикой работы над записью.

bootstrap — подключение реализаций

cmd/api/main.go запускает приложение, собранное в generated/bootstrap/app.go. Bootstrap связывает конфигурацию, репозиторий, сервис, hooks и HTTP-обработчики. Собственные зависимости подключаются через custom composition, поэтому редактировать сгенерированный bootstrap не требуется.

Зависимости пакетов и порядок вызовов

adapters/http ──────→ app/ENTITY_NAME ──────→ domain
adapters/postgres ──→ app/ENTITY_NAME
custom/article ─────→ app/ENTITY_NAME + domain

bootstrap → adapters + app + infrastructure + custom

Стрелки показывают зависимость исходного кода: пакет слева использует контракт справа. При обработке запроса сервис может вызвать PostgreSQL-репозиторий через интерфейс, не импортируя пакет postgres. Custom указывает на владельца реализации, а не добавляет пятый архитектурный слой.

Путь запроса: создание Article

После проверки доступа на HTTP-границе успешное создание записи проходит следующие шаги.

HTTP → Service

Обработчик читает тело запроса, преобразует его в данные сущности и передаёт сервису Article.

validateCreate → BeforeCreate

Сервис проверяет стандартные требования, затем вызывает custom-hook. В нём можно выполнить дополнительную проверку или преобразовать данные.

Repository.Create

PostgreSQL-адаптер записывает данные в БД и возвращает созданную сущность.

AfterCreate → HTTP-ответ

После создания сервис вызывает AfterCreate. Затем результат преобразуется в формат ответа API.

Если BeforeCreate возвращает ошибку, запись не выполняется. AfterCreate вызывается уже после Repository.Create: его ошибка сама по себе не гарантирует откат записи. Если твоим действиям нужна общая транзакция, её поведение нужно явно определить в проекте.

Где добавить свою логику

Используй backend/internal/custom/ENTITY_NAME/hooks.go для проверок и действий в сценариях сущности. Через custom/app/composition.go подключай зависимости. Для отдельных маршрутов предусмотрены custom/app/routes.go и RegisterRoutes. Не редактируй generated bootstrap для подключения расширений.

Практические руководства