Обзор

Это основной макет для проектов приложений на Go. Это не официально определенный стандарт командой разработки Go. Это общепринятая структура каталогов для проектов Go в сообществе.

Если вы изучаете Go или создаете концепцию (PoC) или просто личный проект, этот макет проекта слишком сложен. Вместо этого начните с действительно простого макета (только main.go файл и go.mod достаточно). По мере развития вашего проекта убедитесь, что ваша структура кода хороша, иначе вы получите запутанный код с большим количеством скрытых зависимостей и глобального состояния. Когда в проект вовлекается больше людей, вам потребуется более структурированный подход. В этом случае важно внедрить общепринятые способы управления пакетами/библиотеками. Когда у вас есть проект с открытым исходным кодом или вы знаете, что другие проекты импортируют код из вашего репозитория проекта, становится важным иметь частные (также известные как internal) пакеты и код. Клонируйте репозиторий, сохраните нужные части и удалите все остальное! Просто потому что что-то существует, не обязательно использовать все. Ни один из этих шаблонов не используется в каждом проекте. Даже шаблон vendor не универсален.

Этот макет проекта преднамеренно разработан очень общим и не пытается навязать конкретную структуру пакета Go.

Спецификация каталога проекта Go

Ниже приведена рекомендуемая спецификация каталога проекта Go.

.
├── go.mod
├── api
├── assets
├── build
├── cmd
├── configs
├── deployments
├── docs
├── examples
├── githooks
├── go.mod
├── init
├── internal
├── pkg
├── scripts
├── test
├── third_party
├── tools
├── vendor
├── web
└── website

Ниже приведены значения каждого каталога.

/cmd

Главные приложения проекта, т.е. точки входа программ. Файлы Go в этой директории обычно генерируют исполняемые файлы. В простом проекте файл вроде /test/main.go может служить точкой входа.

Имя директории для каждого приложения должно соответствовать имени исполняемого файла, который вы хотите (например, /cmd/myapp).

Не помещайте слишком много кода в директорию приложения. Если вы считаете, что код можно импортировать и использовать в других проектах, поместите его в директорию /pkg. Если код не подлежит повторному использованию или вы не хотите, чтобы им пользовались другие, поместите код в директорию /internal. Вы удивитесь поведению других людей, поэтому ясно выражайте свое намерение!

Обычно внутри этой директории есть небольшая main функция, которая импортирует и вызывает код из директории /internal и /pkg, и больше ничего.

/internal

Приватный приложенческий и библиотечный код. Это код, который вы не хотите, чтобы другие импортировали в свои приложения или библиотеки. Обратите внимание, что этот шаблон структуры обязателен самим компилятором Go. Для более подробной информации обратитесь к заметкам к релизу для Go 1.4. Обратите внимание, что это не ограничивается только верхним уровнем директории internal. Вы можете иметь несколько internal директорий на любом уровне дерева проекта.

Вы можете выбрать добавлчить дополнительные структуры для внутренних пакетов с целью различения между общим и непубличным внутренним кодом. Это не обязательно (особенно для небольших проектов), но визуальное демонстрирование предполагаемого использования пакетов - хорошая практика. Фактический код вашего приложения может находиться в директории /internal/app (например, /internal/app/myapp), а общий код для этих приложений может размещаться в директории /internal/pkg (например, /internal/pkg/myprivlib).

/pkg

Библиотечный код, который может быть использован внешними приложениями (например, /pkg/mypubliclib). Другие проекты будут импортировать эти библиотеки и ожидать, что они будут работать правильно, поэтому перед размещением содержимого здесь хорошо подумайте :-) Обратите внимание, что директория internal - лучший способ обеспечивать, что приватные пакеты не могут быть импортированы, так как это принудительно устанавливается самим Go. Директория /pkg все равно хороший способ явно передать, что код в этой директории безопасен для использования другими.

Если ваш проект приложения очень мал и многоуровневая вложенность не добавляет много ценности, то это тоже нормально (если вы действительно не хотите этого :-)). Когда проект становится достаточно большим и корневая директория становится очень оживленной, рассмотрите его использование (особенно если у вас множество не-Go компонентов приложений).

/vendor

Зависимости приложения (управляемые вручную или с использованием выбранного вами инструмента управления зависимостями, такого как встроенная функция Go Modules). Команда go mod vendor создаст для вас каталог /vendor. Обратите внимание, что если вы не используете включенную по умолчанию версию Go 1.14, вам может потребоваться добавить флаг -mod=vendor к команде go build.

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

Каталоги Приложений Сервисов

/api

Спецификации OpenAPI/Swagger, файлы схемы JSON, файлы определения протокола и каталоги протокола API.

Каталоги Веб-Приложений

/web

Отдельные компоненты для веб-приложений: статические ресурсы веб-сайта, серверные шаблоны и одностраничные приложения (SPA).

Общие Каталоги Приложений

/configs

Шаблоны файлов конфигурации или конфигурации по умолчанию.

Разместите здесь файлы шаблонов confd или consul-template.

/init

Инициализация системы (systemd, upstart, sysv) и конфигурации менеджера процессов/демона (runit, supervisord).

/scripts

Скрипты для различных операций сборки, установки, анализа и других операций.

/build

Упаковка и непрерывная интеграция.

Разместите конфигурации облачного (AMI), контейнерного (Docker), операционной системы (deb, rpm, pkg) и скрипты в каталоге /build/package.

Разместите конфигурации и скрипты непрерывной интеграции (travis, circle, drone) в каталоге /build/ci. Обратите внимание, что определенные инструменты непрерывной интеграции (например, Travis CI) очень требовательны к расположению их конфигурационных файлов. Попытайтесь разместить файлы конфигурации в каталоге /build/ci и использовать ссылки для подключения их к ожидаемому местоположению инструментов непрерывной интеграции (если это возможно).

/deployments

Конфигурации развертывания и шаблоны для IaaS, PaaS, системы и оркестрации контейнеров (docker-compose, kubernetes/helm, terraform). Обратите внимание, что в некоторых репозиториях (особенно для приложений, развернутых с использованием Kubernetes) этот каталог называется /deploy.

/test

Другие внешние приложения тестирования и тестовые данные. Вы можете организовать каталог /test так, как вам удобно. Для крупных проектов имеет смысл организовать данные в подкаталоги. Например, вы можете создать каталоги /test/data или /test/testdata внутри /test, чтобы игнорировать содержимое Go. Пожалуйста, обратите внимание, что Go также игнорирует каталоги или файлы, начинающиеся с "." или "_", что обеспечивает большую гибкость в именовании каталогов с тестовыми данными.

Другие Каталоги

/docs

Документация по дизайну и пользователя (кроме документов godoc, которые вы генерируете).

/tools

Вспомогательные инструменты для этого проекта. Обратите внимание, что эти инструменты могут импортировать код из каталогов /pkg и /internal.

/examples

Примеры для приложений и/или общедоступных библиотек.

/third_party

Внешние служебные инструменты, форкнутый код и другие сторонние утилиты (например, Swagger UI).

/githooks

Утилиты Git.

/assets

Дополнительные ресурсы (изображения, логотипы и т. д.), предоставленные с репозиторием.

/website

Место для хранения данных веб-сайта проекта, если вы не используете GitHub Pages.

/src

Некоторые проекты на Go могут иметь папку src, но это обусловлено в основном тем, что разработчики приходят из мира Java, где это обычная практика. Пожалуйста, если возможно, постарайтесь избежать принятия этого подобного Java-подобного шаблона. Действительно, вы не хотите, чтобы ваш код на Go или ваш проект выглядел как Java :-)

Не путайте каталог уровня проекта /src с каталогом /src, используемым для рабочего пространства Go, описанного в Как писать код на Go. Переменная среды $GOPATH указывает на ваше (текущее) рабочее пространство (по умолчанию на системах, отличных от Windows, она указывает на каталог $HOME/go). В это рабочее пространство входят верхнеуровневые каталоги /pkg, /bin и /src. Ваш фактический проект будет подкаталогом в каталоге /src, поэтому, если у вас есть каталог /src в проекте, путь проекта будет выглядеть так: /some/path/to/workspace/src/your_project/src/your_code.go. Обратите внимание, что начиная с Go 1.11, ваш проект может находиться за пределами GOPATH, но это не означает, что использование этого шаблона расположения - это хорошая идея.