Пару лет назад, в 13 эпизоде, мы уже затрагивали тему организации проекта. Какие главные принципы организации проекта?
Пакет (package) — это набор связанных файлов .go, находящихся в одной директории.
Каждый файл начинается с
объявления package <имя>
. Пакеты позволяют структурировать код и повторно использовать его.
Например, стандартная библиотека Go содержит пакеты fmt, math/rand и т.д.
Вы можете импортировать их с помощью инструкции import "fmt" и использовать их функции, такие как fmt.Println().
Внутри одного модуля вы можете создавать несколько пакетов, размещая их в отдельных подкаталогах. Это помогает логически разделять функциональность вашего приложения.
Модуль (module) — это коллекция связанных пакетов, объединённых в единое целое с помощью файла go.mod. Модуль определяет границы проекта и управляет зависимостями от других модулей, включая их версии. С помощью модуля вы можете импортировать пакеты из других модулей, указав их путь и версию в go.mod
Для любителей разобраться почему именно такие слова были использованы. До Go 1.11 (24 августа 2018) были только
пакеты. Управление зависимостями было либо ручным (вендоринг, с директорией vendor/
), либо
с использованием сторонних утилит вроде Glide, Godep, Dep etc. Термин пакет уже был
занят!
У подхода есть и свои недостатки - терминологическая база не продумана. Новые термины приходится выдумывать из-за недальновидности при использовании старых.
Этот подход в инженерном деле предлагает начинать с самых простых компонентов и на базе простых решений создавать сложные. Его мы можем применить и при организации файлов проекта.
При этом программа отличается от обычного пакета тем, что в ней есть файл main.go
Эта рекомендация касается любого кода, который потенциально может быть импортирован. В internal
вы можете безопасно менять код без опасения разрушить зависимый код, т.к. internal попросту нельзя импортировать
в другом проекте.
Однако, официальная рекомендация считает, что с самого начала нужно размещать код в internal:
Initially, it’s recommended placing such packages into a directory named internal...
project-root-directory/ go.mod internal/ auth/ ... metrics/ ... model/ ... cmd/ api-server/ main.go metrics-analyzer/ main.go ... ... the project's other directories with non-Go code
Минимализм в структуре: Размещайте main.go в корне проекта, если у вас один исполняемый файл. Это упрощает установку и запуск:
go install github.com/you/project@latest
Избегайте internal/ без необходимости: Папка internal/ ограничивает доступ к коду, но не стоит использовать её без веской причины. Если ваш код не предназначен для широкого переиспользования, достаточно не экспортировать элементы, делая их с маленькой буквы.
Не используйте pkg/ по умолчанию: Ранее pkg/ применялась для размещения библиотек, но сейчас это считается устаревшей практикой. Размещайте пакеты непосредственно в корне проекта.
Избегайте util/, common/, shared/: Такие абстрактные папки затрудняют навигацию. Лучше размещать вспомогательные функции рядом с местом их использования или в тематически названных пакетах.
Не дробите проект на множество пакетов без необходимости: Избыточное количество пакетов усложняет структуру и может привести к циклическим зависимостям. Начните с одного пакета и реорганизуйте структуру по мере роста проекта.
Осторожно с мажорными версиями: Избегайте преждевременного перехода на v2, v3 и т.д. Используйте версии v0.x до тех пор, пока API не стабилизируется, чтобы не усложнять поддержку и использование модуля.