Цель этого задания - подготовить каркас проекта, содержащего основную рутину, для дальнейшего добавления нового функционала.
❗ Структура проекта может меняться и усложняться по мере его развития. Не пытайтесь сразу построить идеальный проект! Лучше сделать структуру простой и гибкой для внесения изменений, чем сложной и запутанной, но соответствующей неким стандартам из идеального мира.
-
Сервис предоставляет
HTTP API
по адресу127.0.0.1:8080
. -
Сервис должен предоставить эндпоинт
GET http://127.0.0.1:8080/api/v1/health
(в дальнейшем будет использоваться для проверки готовности сервиса принимать запросы). Эндпоинт должен возвращать ответ со следующими характеристиками:Content-Type: text/plain. Code: HTTP 200 (OK) Body: HEALTHY
- Разместить проект в отдельном репозитории на
github
(структуру проекта сформировать самостоятельно). - Использовать
Go modules
при установке зависимостей. - Проект должен компилироваться, результат сборки должен быть доступен
в директории
dist
. - Команды компиляции проекта необходимо разместить в
Makefile
. - Проект должен содержать короткую документацию в
README.md
описывающую как работать с проектом и как его собрать. - Все изменения необходимо делать в отдельной ветке в
git
. Когда работа будет закончена, необходимо послатьpool request
в веткуmain
и добавить ментора в ревьюверы.
-
Для построения
api
допускается использовать только библиотекуnet/http
и предлагаемый ею роутер. -
Рекомендуется использовать самую последнюю стабильную версии языка
Go
.
В Go
нет устоявшейся структуры приложения, за исключением каталогов cmd
,
internal
и pkg
. Кроме того, большое количество старого кода написано по
принципу "все файлы лежат в корне проекта". В этом курсе мы будем стараться
следовать современным практикам организации проекта и написания кода.
В настоящее время существует несколько негласных правил формирования структуры проекта. Им не обязательно следовать, но многие коллеги-программисты будут ожидать, что ваш проект устроен именно таким образом.
-
В проектах на
Go
(если это не библиотеки) принято стартовую точку выносить в каталогcmd
и начинать сборку от него. Например, для нашей библиотеки это могло бы выглядеть какcmd/homelibrary/main.go
. У такого подхода есть существенный плюс: можно легко добавить новый исполняемый файл в сборку. Более подробное объяснение можно посмотреть тут. -
Минимальные
main
-файлы и функции, которые содержат 5-7 строк кода: объявление пакета, функция main, вызов некой абстракции, которая запускает приложение, например:package main // Здесь импортируем модуль, в котором живет логика инициализации и запуска // приложения (в примере ниже это app). func main() { if err := app.Run();err != nil { log.Printf("App failed: %v\n", err) os.Exit(1) } }
-
Весь код лежит в каталоге
internal
(в редких случаях вpkg
). Для чего нужен такой каталог можно прочитать тут. На текущий момент импорт кода проекта в других репозиториях не планируется, поэтому весь исходный код рекомендуется сделать приватным. -
Код внутри каталога
internal
имеет структуру/слои. Стоит заранее обдумать где будут жить хэндлерыHTTP API
, куда положить основной код приложения и т.д. Если сейчас это не очевидно, ничего страшного, эти решения все равно придется принять по мере работы над проектом.
ВGo
особенно популярна чистая архитектура, поэтому на нее обязательно стоит хотя бы обратить внимание, например, в проектах из материалов для ознакомления. -
В
Go
при именовании файлов и каталогов принято использовать буквы в нижнем регистре даже если это комбинация из нескольких слов. Исключением может быть использование нижнего подчеркивания, но его чаще вводят как идентификатор группы файлов. В качестве примера рассмотрим возможную структуру одного из модулей проекта:└── internal └─── storage ├── inmemory.go ├── inmemory_mock.go └── inmemory_test.go
Рядом с файлом
inmemory.go
, отвечающим за реализацию хранилища объектов в памяти, расположеныinmemory_test.go
, содержащий юнит-тесты, иinmemory_mock.go
, представляющий собойmock
-реализацию хранилища. Использование нижнего подчеркивания для разделения составного имени на части (например,in_memory.go
) допускается в ряде случаев, но не приветствуется.Кроме того, то, что это хранилище (storage), следует из названия модуля. Дублирование названия модуля в имени сущностей, из которых он состоит, допускается, но не поощряется. Более детально о соглашении по именованию можно прочитать в Naming Conventions in Golang.
-
В
Go
принято именовать модули в единственном числе, например: notification, model, test. Однако из этого правила есть и исключения: utils, docs.
На многие другие вопросы о назначении, расположении и именовании каталогов сможет ответить Go Project Layout. Но будьте осторожны: не стоит слепо следовать его рекомендациям. Многое из описанного в Go Project Layout все еще под вопросом и горячо обсуждается в сообществе. Поэтому при создании структуры в первую очередь руководствуйтесь целесообразностью.
-
Naming Conventions in Golang - содержит рекомендации по именованию модулей, файлов, функций и структур.
-
Go Project Layout - содержит рекомендуемую структуру типичного проекта на Go и описание назначения основных директорий.
-
Clean architecture by Rober C. Martin - оригинальная статья от Роберта Мартина, кратко объясняющая основные идеи чистой архитектуры.
-
Clean architecture with SOLID - шаблон реализации чистой архитектуры с применением принципов SOLID.
-
Go clean template - шаблон реализации проекта по чистой архитектуре Роберта Мартина.
-
Creatly backend - еще один шаблон проекта, построенного по чистой архитектуре.
-
Manage Go tools via Go modules - описывает управление зависимостями с помощью
go mod
. -
Direct vs Indirect Dependencies in go.mod file - об отличии прямых (direct) от непрямых (indirect) зависимостей в
go.mod
.