Який розумний спосіб розмістити проект Go [закритий]


113

У мене є проект, який починає ускладнюватися, і хочу розкласти файлову систему таким чином, щоб зменшити біль.

Чи є якісь хороші приклади, що має сенс?

Відповіді:


132

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

Код Go повинен зберігатися всередині робочої області .
Робоча область - це ієрархія каталогів з трьома каталогами в корені:

  • src містить вихідні файли Go, організовані в пакети (по одному пакету в каталозі),
  • pkg містить об'єкти пакету та
  • bin містить виконувані команди.

go toolБудує вихідні пакети і встановлюють результуючі бінарники до pkgі binкаталогам.

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

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 року: див. " Структурування додатків у роботі " від Бен Джонсон

Ця стаття містить поради, як-от:

Відокремте свій двійковий файл від своєї програми

поєднання main.goфайлу та моєї логіки програми в одному пакеті має два наслідки:

  • Це робить моє додаток непридатним як бібліотека.
  • Я можу мати лише одне двійкове додаток.

Найкращий спосіб, який я вирішив це виправити, - це просто використовувати 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

Користувачі можуть встановити ваші бінарні додатки "adder" із "go get" за допомогою еліпсису:

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

І вуаля, у вашого користувача встановлені " adder" і " adder-server"!

Не збожеволійте за допомогою пакетів

Зазвичай типи мого проекту дуже пов'язані, тому він краще підходить з точки зору зручності використання та API.
Ці типи також можуть скористатися викликом неекспортованого між ними, що забезпечує API невеликим і зрозумілим.

  1. Згрупуйте типи та код, пов’язаний із кожним файлом разом. Якщо ваші типи та функції добре організовані, я вважаю, що файли мають значення від 200 до 500 SLOC. Це може здатись дуже багато, але мені легко переходити. 1000 SLOC зазвичай є моєю верхньою межею для одного файлу.
  2. Упорядкуйте найважливіший тип у верхній частині файлу та додайте типи із зменшенням значення у нижній частині файлу.
  3. Як тільки ваша заявка починає перевищувати 10000 SLOC, ви повинні серйозно оцінити, чи можна її розбити на більш дрібні проекти.

Зауважте: остання практика не завжди є хорошою:

Вибачте, я просто не можу погодитися з цією практикою.
Виділення типу файлів допомагає керувати кодом, читабельністю, збереженням можливостей, тестабельністю.
Це також може забезпечити єдину відповідальність та дотримання принципу відкритого / закритого…
Правило заборонити кругову залежність - це змусити нас мати чітку структуру пакетів.


(Альтернативно, лютий 2013 року, стосується srcлише)
Класичний макет можна проілюструвати в " Макет коду GitHub ":

Додаток та обидві бібліотеки живуть у 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 checkout.

Хоча це викликало критику на цій сторінці для редагування :

Я настійно рекомендую не структурувати репо, як у вас є, він порушиться " go get", що є однією з найкорисніших речей про Go.
Набагато краще написати свій код для людей, які знають, що йдуть Go, оскільки вони, швидше за все, саме ті, хто їх компілює.
А для людей, які цього не роблять, вони принаймні відчують мову.

Покладіть основний пакет в корінь репо.
Майте активи в підкаталозі (щоб все було чітко).
Зберігайте м'ясо коду в підпаку (якщо хтось хоче повторно використовувати його поза вашим бінарним файлом).
Включіть сценарій налаштування в корінь репо, щоб його легко знайти.

Це ще лише процес, який завантажують, встановлюють та встановлюють у два кроки:

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

15
Одна з великих проблем setup.shполягає в тому, що Go є досить кросплатформенним, тоді як сценарії оболонки POSIX - ні.
kostix

Структура jmcvetta не порушиться get get, оскільки марний імпорт марний, go get встановиться як з go get ... / uselessd. Але я погоджуюсь, що якщо марною є бібліотека, спеціально створена для безполезних, то має сенс зберігати її в одному gpo repo, як підпапку або братів і сестер.
mna

@PuerkitoBio Я згоден. Моє навчання контролю версій та управління компонентами ( stackoverflow.com/a/933735/6309 ) приводить мене більше до одного компонента за репо, отже, до другої частини цієї відповіді.
VonC

7

Я припускаю, що під проектом ви маєте на увазі не пакет програм Go, а програмне забезпечення, яке ви розробляєте. Інакше можна отримати допомогу тут і тут . Однак це не так сильно відрізняється від написання пакетів для Go: Використовуйте пакети, створюйте папки для кожного пакету та комбінуйте ці пакунки у вашій програмі.

Щоб скласти собі думку, ви можете переглянути тенденційні сховища Go на github: https://github.com/trending/go . Характерними прикладами є Кейлі і Zeus .

Найпопулярніша схема, мабуть, має головний файл Go та багато модулів та підмодулів у власних каталогах. Якщо у вас багато метафайлів (doc, ліцензія, шаблони, ...), можливо, ви захочете ввести вихідний код у підкаталог. Ось що я робив досі.


@aussiegeek, я не експерт Go, але я успішно застосував те, що неможливо запропонував у власному коді - ідея полягає в тому, що ви можете мати модулі під своїм каталогом проектів, просто потрібно посилатися на них, використовуючи їх повний префікс - відносний до $GOPATH/srcабо з використанням їх go get-табельних імен.
kostix

doozerdце не гарний приклад, навіть його тести слабкі.
Inanc Gumus

@InancGumus Я рекомендую вам запропонувати кращий приклад.
nemo

бачити це і це .
Inanc Gumus

1

Авторами Golang є рекомендований підхід, який визначає, як компонувати код, щоб найкраще працювати з інструментами go і підтримувати системи управління джерелами


1
Ось як компонувати $GOROOT, а не код всередині src/<project>каталогу.
docwhat

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.