Главная / Блог / Go-clean-template

Go-clean-template: шаблон чистой архитектуры для сервисов на Go

July 2021

Go-clean-template — шаблон для проектов на Golang, основанный на принципах чистой архитектуры Роберта («дядюшки Боба») Мартина. Вы можете клонировать шаблон и использовать его в качестве отправной точки для создания приложения на языке Go.

Чистая архитектура

Чистая архитектура — это способ организации кода сложных систем (в том числе потенциально сложных), который, как и большинство хороших сводов архитектурных принципов, способствует строгому разделению ответственности. Изначально предполагался для использования в монолитах, но так же подходит и к микросервисам.

Программное обеспечение разбивается на независимые функциональные компоненты, которые взаимодействуют друг с другом только определённым надёжным способом, при этом между ними передаётся только то состояние и те ресурсы, которыми необходимо обмениваться для выполнения поставленной задачи. Строгое разделение ответственности помогает минимизировать сложность каждого компонента, снижает вероятность появления ошибок, а если они возникли, облегчает их устранение, так как компонент-нарушитель можно легко идентифицировать. Разделение ответственности — ключ к соблюдению принципа «минимальных привилегий».

Чистая архитектура разделяет ответственность с помощью конвенций (правил), которые ясно дают понять, где в архитектуре сущность, а где компонент или часть компонента, и в какой степени каждый из них виден и доступен для других частей системы.

Если вы придерживаетесь принципов чистой архитектуры, то, например, высокоуровневые корпоративные бизнес-правила системы не будут иметь прямого доступа к структурам данных, передаваемых между API-сервером и мобильным приложением, и даже не будут знать о существовании таких деталей. Однако, если необходимо, их содержимое может передаваться через слои от низкоуровневых компонентов к вышестоящим чётко определёнными способами.

Как любая архитектурная основа, чистая архитектура сама по себе не убережёт от написания плохого кода, если вы не будете сознательно следовать её принципам на протяжении всего жизненного цикла приложения.Тем не менее, надеемся, что этот шаблон поможет вам правильно начать.

Краткое руководство

После того, как вы  сделали копию шаблона, вы можете войти в папку internal и начать писать код. Предоставляемый Makefile содержит ряд целей для сборки и запуска вашего приложения. Наиболее полезны следующие:

Запуск с помощью Docker (запускает Postgres и RabbitMQ):

$ make compose-up

Запуск локально с миграциями:

$ make run

Запуск интеграционных тестов с помощью Docker:

$ make compose-up-integration-test

Структура проекта

Полную информацию вы найдете в README проекта, но вот некоторые особо интересные области:

cmd/app/main.go

Конфигурация и инициализация логгера, перед передачей управления в Run в файле internal/app/app.go.

internal/app

Функция Run (которую вызывает Main) в app.go выполняет инициализацию объектов и внедрение зависимостей (подробнее об этом ниже), запускает сервер и ждёт, когда наступит время для штатного завершения.

Файл migrate.go используется для автоматической миграции базы данных. Он включается, если указан аргумент с тегом migrate. Например: 

$ go run -tags migrate ./cmd/app

internal/controller

Уровень обработчиков серверов (контроллеры MVC). Шаблон включает в себя два сервера:

  • RPC (RabbitMQ как транспорт)
  • REST HTTP (фрейморк Gin)

Маршрутизаторы запросов написаны в том же стиле:

  • обработчики группируются по области применения;
  • для каждой группы создается своя структура маршрутизатора, методы которой обрабатывают пути;
  • в структуру маршрутизатора вносится структура бизнес-логики, которая будет вызываться обработчиками.

internal/entity

Модели бизнес-логики, которые являются общими для системы и могут быть использованы в любом слое.

internal/usecase

Бизнес-логика:

  • методы группируются по областям применения (на общей основе);
  • каждая группа имеет свою собственную структуру;
  • один файл — одна структура.

config/config.yml

Конфигурация приложения. Значения из файла конфигурации можно переопределить с помощью переменных окружения. Параметры конфигурации с тегом 'env-required: true' в config.go являются обязательными, и значение должно быть указано либо в config.yml, либо в окружении, либо и там, и там.

docs/

Документация Swagger. Она автоматически генерируется библиотекой swag, поэтому нет смысла вносить в неё изменения, они всё равно не сохранятся.

integration-test/

Интеграционные тесты. Они запускаются как отдельный контейнер рядом с контейнером приложения. Rest API удобно тестировать с помощью go-hit.

Внедрение зависимости

Внедрение зависимостей ослабляет связь между компонентами и сводит к минимуму прямые зависимости.

Например, через конструктор New внедряем зависимость в структуру бизнес-логики. Это делает бизнес-логику независимой (и переносимой). Мы можем переопределить реализацию интерфейса, не внося изменений в пакет usecase.

package usecase

import (
    // Nothing!
)

type Repository interface {
    Get()
}

type UseCase struct {
    repo Repository
}

func New(r Repository) *UseCase {
    return &UseCase{
        repo: r,
    }
}

func (uc *UseCase) Do()  {
    uc.repo.Get()
}

Это также позволяет автоматически генерировать моки (например, с помощью mockery) и легко писать юнит-тесты.

Мы не привязаны к конкретным реализациям и всегда имеем возможность заменить один компонент на другой. Если новый компонент реализует интерфейс, то в бизнес-логике ничего менять не нужно.

Когда нужно управлять большим количеством внедрений, часто используют wire.

Альтернативные проекты

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

go-clean-arch

courses-backend
 
Мы работаем над проектами с открытым исходным кодом, потому что инициативны и понимаем, что нравится и нужно разработчикам. Если вам требуется обновить свой проект до последних версий технологического стека, свяжитесь с нами через форму ниже.

Проблемы с архитектурой часто возникают после того, как большая часть проекта уже написана. А чистая архитектура помогает отсрочить принятие решений, делая ваш код более простым и удобным для сопровождения.
Михаил Непряхин
ключевой разработчик go-clean-template, Evrone
Будем на связи
Прикрепить файл
Максимальный размер файла: 2 МБ.
Допустимые типы файлов: jpg jpeg png txt rtf pdf doc docx ppt pptx.