23 KiB
Executable File
Standard Go Project Layout
Translations:
Overview
Это базовый макет организации проектов, разработанных на Golang. Это не официально определенный командой разработчиков Golang стандарт, однако он удовлетворяет исторически сложившимся шаблонам организации проекта в экосистеме Golang. Некоторые из шаблонов могут быть известнее остальных. В макете также присутствуют несколько улучшений, включая дополнительные директории, используемые в любом достаточно большом реальном приложении.
Если вы пытаетесь изучить Golang или собрать маленький обучающий проект для личного пользования, данный макет будет явным перебором. Стоит начать с чего-нибудь действительно простого (одного файла main.go будет достаточно). Как только ваш проект начнет расти, стоит задуматься о важности содержания кода в структурированном состоянии, чтобы в конечном итоге не получить грязный код с множеством скрытых зависимостей и global state. А когда над проектом начнут работать другие люди - понадобится еще большая структуризация. В этот момент важно определить стандартный путь организации пакетов/библиотек. Если вы разрабатываете проект с открытым исходным кодом или знаете, что вашим кодом будут пользоваться при разработке других проектов, необходимо понимать важность создания личных, внутренних (или internal) пакетов и кода. Клонируйте репозиторий, пользуйтесь тем, что действительно нужно, и удалите всё остальное! Наличие этого "всего остального" вовсе не означает, что это обязательно использовать. Заметьте, что ни один из этих шаблонов не обязан быть использован в абсолютно каждом проекте. Даже vendor не может быть универсален во всех случаях.
С выходом обновления Golang 1.14, Go Modules стали наконец-то доступны для использования. Применяйте Go Modules везде, пока не столкнётесь с веской причиной отказаться от них, и если такой момент всё же настанет - вам больше не придётся волноваться о значении переменной окружения $GOPATH и месте, где вы размещаете свой проект. Базовый go.mod файл в репозитории показывает, что ваш проект размещён на GitHub, однако он не является обязательным. Путь к модулю может быть любым, при условии, что первый компонент пути должен содержать точку в имени (текущая версия Golang больше не требует этого, но если вы используете достаточно устаревшие версии - не стоит удивляться, что ваши сборки могу перестать работать). Ознакомьтесь с проблемами: 37554 и 32819 если хотите узнать об этом больше.
Этот шаблон организации проекта намеренно сделан обобщенным, и не является примером структуры какого-то конкретного пакета Golang.
Этот репозиторий открыт к усилиям сообщества. Создайте заявку о проблеме, если вы нашли новый шаблон или считаете, что один из существующих шаблонов необходимо обновить.
Если вам нужна помощь в наименовании, форматировании или стилизации кода - начните с gofmt и golint. Также обязательно прочтите эти руководства по стилизации кода Golang и рекомендации:
- https://talks.golang.org/2014/names.slide
- https://golang.org/doc/effective_go.html#names
- https://blog.golang.org/package-names
- https://github.com/golang/go/wiki/CodeReviewComments
- Руководство по стилизации кода для пакетов Golang (rakyll/JBD)
Обратите внимание на Шаблон проекта Golang для получения дополнительной информации.
Еще больше про наименование и организацию пакетов, а так же про структуру кода можно узнать здесь:
- GopherCon EU 2018: Peter Bourgon - Best Practices for Industrial Programming
- GopherCon Russia 2018: Ashley McNamara + Brian Ketelsen - Go best practices.
- GopherCon 2017: Edward Muller - Go Anti-Patterns
- GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps
Пост о руководствах по пакетноориентированному дизайну и макетам архитектур
Директории Go
/cmd
Основные приложения проекта.
Имя директории для каждого приложения должно совпадать с именем исполняемого файла, который вы хотите собрать (например, /cmd/myapp).
Не стоит располагать в этой директории большие объёмы кода. Если вы предполагаете дальнейшее использование кода в других проектах, вам стоит хранить его в директории /pkg в корне проекта. Если же код не должен быть переиспользован где-то еще - ему самое место в директории /internal в корне проекта. Вы будете удивлены тем, что другие люди могут сделать, поэтому будьте уверены в своих намерениях!
Самой распространнёной практикой является использование маленькой main функции, которая импортирует и вызывает весь необходимый код из директорий /internal и /pkg и никаких других.
Ознакомьтесь с директорией /cmd для примера.
/internal
Внутренний код приложения и библиотек. Это код, который не должен быть применен в других приложениях и библиотеках. Стоит отметить, что этот шаблон навязан самим компилятором Golang. Ознакомьтесь с release notes Go 1.4. Также, вы вольны использовать internal директорию на разных уровнях своего проекта.
Вы можете добавить дополнительное структурирование, чтобы разделить открытую и закрытую части вашего внутреннего кода. Такой подход не является необходимым, особенно для маленьких проектов, но позволяет сразу визуально оценить применение кода. Код самого приложения может находиться в директории /internal/app (например, /internal/app/myapp), а код, который это приложение использует - в директории /internal/pkg (например, /internal/pkg/myprivlib).
/pkg
Код библиотек, пригодных для использования в сторонних приложениях. (например, /pkg/mypubliclib). Другие проекты будут импортировать эти библиотеки, ожидая их автономной работы, поэтому стоит подумать дважды, прежде чем класть сюда какой-нибудь код :-) Заметьте, что использование директории internal - более оптимальный способ не дать импортировать внутренние пакеты, потому что это обеспечит сам Golang. Директория /pkg - всё еще хороший путь дать понять, что код в этой директории могут безопасно использовать другие. Пост I'll take pkg over internal в блоге Трэвиса Джеффери предоставляет хороший обзор директорий pkg и internal и когда есть смысл их использовать.
Существует возможность группировать код на Golang в одном месте, когда ваша корневая директория содержит множество не относящихся к Go компонентов и директорий, что позволит облегчить работу с разными инструментами Go (как упомянуто в этих разговорах: Best Practices for Industrial Programming с GopherCon EU 2018, GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps и GoLab 2018 - Massimiliano Pippi - Project layout patterns in Go).
Ознакомьтесь с директорией /pkg, если хотите увидеть, какие популярные репозитории используют такой шаблон организации проекта. Несмотря на его распространенность, он не был принят всеми, а некоторые в сообществе Go и вовсе не рекомендует его использовать.
Вы можете не использовать эту директорию, если проект совсем небольшой и добавление нового уровня вложенности не имеет практического смысла (разве что вы сами этого не хотите :-)). Подумайте об этом, когда ваша корневая директория начинает слишком сильно разрастаться, особенно, если у вас много компонентов, написанных не на Go.
/vendor
Зависимости приложений, управляемые вручную или с использованием вашей любимой системы управления зависимостями, вроде новых встроенных Go Modules). Команда go mod vendor создаст для вас директорию /vendor. Заметьте, что вам возможно придётся добавить флаг -mod=vendor к команде go build, если вы используете версию, отличную от Go 1.14, где такой флаг выставлен по-умолчанию.
Не стоит отправлять зависимости вашего приложения в репозиторий, если собираетесь создавать библиотеку.
Стоит отметить, что с версии 1.13 Go добавил возможность проксирования модулей (с использованием https://proxy.golang.org как прокси-сервера по-умолчанию). Здесь можно побольше узнать про эту возможность, чтобы убедиться, что она удовлетворяет вашим необходимостям и ограничениям. Если это так - использование директории vendor не требуется вовсе.
Директории приложений-сервисов
/api
Спецификации OpenAPI/Swagger, файлы JSON schema, файлы определения протоколов.
Ознакомьтесь с директорией /api для примеров.
Директории Веб-приложений
/web
Специальные компоненты для веб-приложений: статические веб-ресурсы, серверные шаблоны и одностраничные приложения.
Распространенные директории
/configs
Шаблоны файлов конфигураций и файлы настроек по-умолчанию.
Положите файлы конфигураций confd или consul-template сюда.
/init
Файлы конфигураций для процессов инициализации системы (systemd, upstart, sysv) и менеджеров процессов (runit, supervisord).
/scripts
Скрипты для сборки, установки, анализа и прочих операций над проектом.
Эти скрипты позволяют оставить основной Makefile небольшим и простым (например, https://github.com/hashicorp/terraform/blob/master/Makefile).
Ознакомьтесь с директорией /scripts для примеров.
/build
Сборка и непрерывная интеграция (Continuous Integration, CI).
Поместите файлы конфигурации и скрипты облака (AMI), контейнера (Docker), пакетов (deb, rpm, pkg) в директорию /build/package.
Поместите ваши файлы конфигурации CI (travis, circle, drone) и скрипты в директорию /build/ci. Заметьте, что некоторые инструменты CI (например, Travis CI) очень требовательны к расположению их конфигурационных файлов. Попробуйте поместить их в директорию /build/ci создав ссылку на них в месте, где их ожидают найти инструменты Go (если возможно).
/deployments
Шаблоны и файлы конфигураций систем оркестраций IaaS, PaaS, операционных систем и контейнеров (docker-compose, kubernetes/helm, mesos, terraform, bosh). Отметьте, что в некоторых репозиториях, особенно в приложениях, развернутых с использованием Kubernetes, эта директория называется /deploy.
/test
Дополнительные внешние приложения и данные для тестирования. Вы вольны организовывать структуру директории /test так, как вам угодно. Для больших проектов имеет смысл создавать вложенную директорию с данными для тестов. Например,/test/data или /test/testdata, если вы хотите, чтобы Go игнорировал находящиеся там файлы. Отметьте, что Go будет также игнорировать файлы, путь к которым начинается с "." или "_", что предоставляет вам гибкость в наименовании вашей папки с тестами.
Ознакомьтесь с директорией /test для примеров.
Другие Директории
/docs
Документы пользователей и дизайна (в дополнение к автоматической документации godoc).
Ознакомьтесь с директорией /docs для примеров.
/tools
Инструменты поддержки проекта. Отметьте, что эти инструменты могут импортировать код из директорий /pkg и /internal.
Ознакомьтесь с директорией /tools для примеров.
/examples
Примеры ваших приложений и/или библиотек.
Ознакомьтесь с директорией /examples для примеров.
/third_party
Внешние вспомогательные инструменты, ответвления кода и другие сторонние утилиты (например, Swagger UI).
/githooks
Git hooks.
/assets
Другие ресурсы, необходимые для работы (картинки, логотипы и т.д.)
/website
Здесь можно разделить файлы для вебсайта вашего проекта, если вы не используете GitHub pages.
Ознакомьтесь с директорией /website для примеров.
Директории, которые не стоит размещать у себя в проекте
/src
Некоторые проекты на Go имеют директорию src, но это обычно происходит, когда разработкой занялся человек, пришедший из мира Java, где такой подход весьма распространен. Постарайтесь не использовать его в разработке на Golang, если не хотите, чтобы ваш код или проект выглядел, будто написан на Java :-).
Не путайте директорию уровня проекта /src с директорией /src, которую Go использует для своих рабочих пространств, как это описано в How to Write Go Code. Переменная окружения $GOPATH указывает на ваше текущее рабочее пространство (по-умолчанию - $HOME/go на системах под управлением ОС, отличной от Windows). Это рабочее пространство включает высокоуровневые директории /pkg, /bin и /src. Ваш проект в свою очередь находится во вложенной в /src директории, поэтому если вы имеете директорию /src внутри вашего проекта, путь к нему будет выглядеть примерно так: /some/path/to/workspace/src/your_project/src/your_code.go. Отметьте, что в версиях после Go 1.11 возможно хранить проект отдельно от локации, описанной в GOPATH, но это всё еще не значит, что применять этот Java-шаблон - хорошая идея.
Badges
-
Go Report Card - Просканирует ваш код с помощью
gofmt,go vet,gocyclo,golint,ineffassign,licenseиmisspell. Заменитеgithub.com/golang-standards/project-layoutна ссылку на ваш проект. -
GoDoc - Предоставит онлайн версию вашей сгенерированной GoDoc документации
-
Pkg.go.dev - Pkg.go.dev is a new destination for Go discovery & docs. You can create a badge using the badge generation tool.
-
Release - Покажет версию последнего релиза вашего проекта.