В этой истории я хочу представить настройку своего проекта для приложений, написанных на Go. Он хорошо подходит для больших приложений, которые обслуживают команды cmd, пользовательские интерфейсы, API или все сразу. Я потратил много времени на размышления о том, где разместить вещи в моих проектах Go, поэтому я хочу поделиться с вами результатом, чтобы обеспечить разумную основу для вашего следующего проекта Go. Несмотря на рекомендации конкретных библиотек для конкретных задач, фактическая структура папок не привязана к этим библиотекам, ее можно использовать с любыми существующими альтернативами. Итак, давайте не будем терять время и начнем с фактической структуры папок:

команда

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

внутренний

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

Импорт пути, содержащего элемент «внутренний», запрещен, если код импорта находится вне дерева, корнем которого является родитель «внутреннего» каталога.

Я не часто помещаю код во внутреннюю папку, потому что в прошлом я иногда сталкивался с проблемой, что я хотел использовать внутренний код в своих собственных пакетах, но из-за этого правила я не мог этого сделать. Поэтому я бы предложил использовать эту папку только для кода, который завернут в другие файлы за пределами внутренней папки и который вы не хотите, чтобы кто-либо импортировал напрямую.

упаковка

Папка pkgодна из самых важных, она содержит основные части логики приложения, которые предназначены для импорта другими пакетами. В своих проектах я создаю подпапки для любой конкретной группы логики, которую хочу сделать общедоступной. Примеры, которые я написал: pkg/ssh для абстракции, которая выполняет действия через ssh, или pkg/cmd для переноса использования выполнения команд cmd из моего приложения.

Примечание. В блоге есть интересная запись о pkg и внутренней папке.

модели

Если вы работаете с какой-либо базой данных и соответствующей ORM для подключения к ней (например, gorm), имеет смысл создать специальную папку для этих моделей. Вы можете импортировать модели из любого другого места. Поскольку go позволяет настраивать различные виды использования полей с помощью отражения тегов, например. json или gorm, в основном нет необходимости писать несколько структур для модели, которая будет обрабатываться разными пакетами.

Примечание. Вы также можете перемещать модели в подпапки каталога pkg, если они основаны на определенной логике, например. модель SshConfig также может находиться в pkg/ssh вместо models . Это зависит от вашей собственной благосклонности.

API

Если ваше приложение предоставляет какой-либо API для подключения (например, gRPC, HTTP, …), папка api — это правильное место для размещения любых схем или спецификаций. Вы также можете добавить сюда маршруты конечных точек API. Другим разработчикам легко получить представление о том, какие конечные точки предоставляет ваше приложение.

ui

Если вы хотите создать приложение с графическим интерфейсом (вместо приложения cli или даже в сочетании с ним), перемещение элементов, связанных с пользовательским интерфейсом, в определенную папку — хороший способ отделить ее от остальных. Лично я предпочитаю Wails для разработки приложений с графическим интерфейсом на Go. Это легкая библиотека, использующая собственный WebView вместо Electron, предоставляет список доступных стартеров (я предпочитаю React с Typescript), и ее легко использовать.

библиотека

На первый взгляд вы можете подумать, что lib звучит как конфликт с pkg , обе папки являются папками для хранения кода, который следует повторно использовать в текущем или любом другом модуле, который его импортирует. Но я думаю, что папка lib может служить другой цели: объединение основной логики приложения, чтобы сделать его пригодным для использования из cli и части пользовательского интерфейса. Давайте рассмотрим команду build, которую нужно экспортировать в UI и в cmd. Для этого мы переносим все доступные аргументы cmd для команды сборки в структуру с именем BuildArgs в lib/build.go. Кроме того, функция с именем func Build(args *BuildArgs) экспортируется из lib/build.go. Часть cmd теперь может просто обернуть аргументы cmd в структуру BuildArgs и вызвать функцию Build. Часть пользовательского интерфейса может собирать необходимые данные от пользователя и действовать таким же образом. Итак, в моих проектах папка lib содержит основные функции приложения, которые планируется повторно использовать с различными типами пользовательского ввода.

сценарии

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

инструменты

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

утилиты

Эта папка, пожалуй, самая опасная из представленных здесь. В utils вы можете в основном поместить все, что не связано с какой-либо конкретной частью логики, но является более общим помощником, который можно использовать в разных местах. Однако вы должны быть осторожны, прежде чем добавлять какой-либо код в папку utils: вообще, даже вспомогательные функции должны располагаться либо в каталоге internal, либо в каталоге pkg, к которому они логически подходят. И легко создать корзину функций и структур в папке util, чтобы не думать о том, как их можно интегрировать в реальную структуру проекта. Поэтому будьте осторожны, размещая код в этой папке.

Краткое содержание

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

Вдохновлено:
https://github.com/golang-standards/project-layout
https://dev.to/jinxankit/go-project-structure-and-guidelines -4ccm
https://tutorialedge.net/golang/go-project-structure-best-practices/