Что такое разумный способ компоновки проекта Go

У меня есть проект go, который начинает становиться более сложным и хочет выложить файловую систему таким образом, чтобы уменьшить боль.

Есть ли хорошие примеры того, что имеет смысл?

Ответ 1

Обновление в мае 2013 года: официальная документация находится в разделе " Организация кода"

Код go должен храниться внутри рабочей области.
Рабочее пространство представляет собой иерархию каталогов с тремя директориями в корне:

  • src содержит исходные файлы Go, организованные в пакеты (один пакет для каталога),
  • pkg содержит объекты пакета и
  • bin содержит исполняемые команды.

go tool создает исходные пакеты и устанавливает результирующие двоичные файлы в каталоги pkg и bin.

Подкаталог src обычно содержит несколько репозиториев управления версиями (например, для Git или Mercurial), которые отслеживают разработку одного или нескольких исходных пакетов.

bin/
    streak                         # command executable
    todo                           # command executable
pkg/
    linux_amd64/
        code.google.com/p/goauth2/
            oauth.a                # package object
        github.com/nf/todo/
            task.a                 # package object
src/
    code.google.com/p/goauth2/
        .hg/                       # mercurial repository metadata
        oauth/
            oauth.go               # package source
            oauth_test.go          # test source

Обновление июля 2014 года: см. Структурирование приложений в Go "из Бен Джонсон

В эту статью входят следующие советы:

Отделите свой бинарный файл от приложения

объединение файла main.go, а моя логика приложения в том же пакете имеет два следствия:

  • Это делает мое приложение непригодным для использования в качестве библиотеки.
  • У меня может быть только одно приложение.

Лучший способ, которым Ive решил исправить это, - просто использовать каталог "cmd" в моем проекте, где каждый из его подкаталогов является двоичным приложением приложения.

camlistore/
  cmd/
    camget/
      main.go
    cammount/
      main.go
    camput/
      main.go
    camtool/
      main.go

Разработка, управляемая библиотекой

Перемещение файла main.go из вашего корня позволяет вам создавать приложение с точки зрения библиотеки. Бинарный файл приложения - это просто клиент вашей библиотеки приложений.

Иногда вы можете захотеть, чтобы пользователи взаимодействовали несколькими способами, чтобы создать несколько двоичных файлов.
Например, если у вас есть пакет "adder", который позволяет пользователям добавлять номера вместе, вы можете захотеть выпустить версию командной строки, а также веб-версию.
Вы можете легко сделать это, организовав свой проект следующим образом:

adder/
  adder.go
  cmd/
    adder/
      main.go
    adder-server/
      main.go

Пользователи могут установить двоичные файлы приложений "сумматор" с помощью "go get" с помощью многоточия:

$ go get github.com/benbjohnson/adder/...

И воля, у вашего пользователя установлены "adder" и "adder-server"

Не сходите с подпакетов

Обычно мои типы проектов очень взаимосвязаны, поэтому он лучше подходит для удобства использования и API.
Эти типы также могут использовать вызовы, не поддерживаемые между ними, что делает API небольшим и понятным.

  • Группируйте связанные типы и код вместе в каждом файле. Если ваши типы и функции хорошо организованы, я обнаружил, что файлы, как правило, составляют от 200 до 500 SLOC. Это может показаться много, но мне легко ориентироваться. 1000 SLOC обычно является моим верхним пределом для одного файла.
  • Организуйте наиболее важный тип в верхней части файла и добавьте типы, уменьшающие важность в нижней части файла.
  • Как только ваше приложение начнет получать более 10 000 SLOC, вы должны серьезно оценить, может ли он быть разбит на более мелкие проекты.

Примечание: эта последняя практика не всегда хороша:

Извините, я просто не могу согласиться с этой практикой.
Разделение типа на файлы помогает управлять кодом, читабельности, материнствам, тестируемости.
Он также может обеспечить единую ответственность и следовать принципу открытого/закрытого...
Правило не допускать круговой зависимости состоит в том, чтобы заставить нас иметь четкую структуру пакетов.


(Альтернативный февраль 2013 года, касающийся только src)
Вы можете найти классический макет, показанный в " GitHub Code Layout ":

Приложение и обе библиотеки живут в Github, каждый в своем собственном репозитории.
$GOPATH - это корень проекта - каждый из ваших репозиториев Github будет проверен несколькими папками ниже $GOPATH.

Схема вашего кода будет выглядеть так:

$GOPATH/
    src/
        github.com/
            jmcvetta/
                useless/
                    .git/
                    useless.go
                    useless_test.go
                    README.md
                uselessd/
                    .git/
                    uselessd.go
                    uselessd_test.go
                    README.md

Каждая папка под src/github.com/jmcvetta/ является корнем отдельной проверки Git.

Это привлекло некоторые критические замечания, хотя на этой странице reddit:

Я очень рекомендую не структурировать репо, как у вас, он сломает "go get", что является одной из самых полезных вещей о Go.
Гораздо лучше написать свой код для людей, которые знают Go, поскольку они, скорее всего, будут их компиляцией.
И для людей, которые этого не делают, они, по крайней мере, почувствуют себя на этом языке.

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

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

  • "go get <your repo path>": загружает и устанавливает код go, с поддиретом для активов
  • $GOPATH/<your repo path>/setup.sh: распределяет активы в нужном месте и устанавливает сервис

Ответ 2

Я предполагаю, что с "проектом" вы не имеете в виду пакет Go, а разрабатываете программное обеспечение. В противном случае вы можете получить помощь здесь и здесь. Однако это не так сильно отличается от написания пакетов для Go: использование пакетов, создание папки для каждого пакета и объединение этих пакетов в ваше приложение.

Чтобы создать собственное мнение, вы можете посмотреть трендовые Go repositories на github: https://github.com/trending/go. Известными примерами являются cayley и zeus.

Самая популярная схема - вероятно, иметь основной файл Go и множество модулей и подмодулей в своих собственных каталогах. Если у вас много метафайлов (doc, license, templates,...), вы можете захотеть поместить исходный код в подкаталог. Это то, что я сделал до сих пор.

Ответ 3

Существует рекомендуемый подход от авторов Golang, который определяет, как развернуть свой код, чтобы лучше работать с инструментами go и поддерживать источник системы управления