Организация многофайлового проекта Go [закрыто]

238

Примечание: этот вопрос связан с этим один , но два года очень долгое время в истории Go.

Каков стандартный способ организации проекта Go во время разработки?

Мой проект представляет собой отдельный пакет mypack, поэтому я полагаю, что все файлы .go помещены в mypackкаталог.

Но затем я хотел бы проверить это во время разработки, поэтому мне нужен хотя бы файл, объявляющий mainпакет, чтобы я мог сделатьgo run trypack.go

Как мне это организовать? Нужно ли делать go install mypackкаждый раз, когда я хочу попробовать?

Блэксад
источник
14
Эта короткая заставка потрясающая: youtube.com/watch?v=XCsL89YtqCs
Мэтт,
Это еще одна полезная ссылка для понимания того, как организовать проект с пакетами. Легче следовать, чем официальный Как написать код, я думаю.
IamNaN
Для новой системы модулей Go этот ответ охватывает структуру модулей, организацию пакетов в модуле, наличие нескольких модулей в одном репозитории и т. Д. В конечном итоге официальный вводный документ «Как писать код Go» будет обновлен для модулей. , но этого еще не произошло. (Если вы новичок в Go и новички в модулях Go, все же стоит прочитать этот документ «Как написать код Go», прежде чем читать больше о модулях, учитывая, что большая часть документации по модулям предполагает знакомство с GOPATH).
типичная182

Ответы:

171

Я бы порекомендовал просмотреть эту страницу на Как написать код Go

Он документирует, как правильно структурировать ваш проект go build, а также как писать тесты. Тесты не должны быть cmd с использованием mainпакета. Они могут быть просто именованными функциями TestX как часть каждого пакета, а затем go testобнаружат их.

Структура, предложенная в этой ссылке в вашем вопросе, немного устарела, теперь с выпуском Go 1. Вам больше не нужно размещать pkgкаталог под src. Единственные 3 директории, связанные со спецификацией, - это 3 в корне вашей GOPATH: bin, pkg, src. Под src вы можете просто поместить свой проект mypack, а под ним - все ваши файлы .go, включая mypack_test.go

go build затем встроит в корневой уровень pkg и bin.

Так что ваша ГОПАТА может выглядеть так:

~/projects/
    bin/
    pkg/
    src/
      mypack/
        foo.go
        bar.go
        mypack_test.go

export GOPATH=$HOME/projects

$ go build mypack
$ go test mypack

Обновление: начиная с> = Go 1.11, система Module теперь является стандартной частью оснастки, и концепция GOPATH близка к устареванию.

JDI
источник
26
Используйте $ HOME вместо ~ при экспорте переменных.
Йохан С.
6
Почему $ HOME рекомендуется более ~ при экспорте переменных?
425
8
Потому что ~ не переменная, просто псевдоним.
Пих
6
@ 425nesp Йохан ошибается - это не так. Оболочки различаются, но bash расширяется ~при настройке переменных среды , как и, например, оболочка busybox bourne. Попробуй сам: export BOB=~ && env | grep ^BOBуступитBOB=/your/homedir
Остин Адамс
1
$HOMEработает в большем количестве оболочек ~, например, вfish
hoijui
60

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

~/projects/src/
    myproj/
        mypack/
            lib.go
            lib_test.go
            ...
        myapp/
            main.go

Выполнение go build myproj/mypackсоздаст mypackпакет вместе с его зависимостями. Выполнение go build myproj/myappсоздаст myappдвоичный файл вместе с его зависимостями, которые, вероятно, включают mypackбиблиотеку.

Джереми Уолл
источник
Это имело бы смысл, конечно, если бы у него действительно был основной cmd. Похоже, он просто создает библиотечный пакет.
2012 года
50

Я изучил несколько проектов Go, и есть немало вариантов. Вы можете сказать, кто идет из C, а кто из Java, поскольку первый дамп почти всего в корневом каталоге проектов в mainпакете, а второй, как правило, помещает все в srcкаталог. Ни то, ни другое не является оптимальным. У каждого есть последствия, потому что они влияют на пути импорта и то, как другие могут их использовать.

Чтобы получить наилучшие результаты, я разработал следующий подход.

myproj/
  main/
    mypack.go
  mypack.go

Где mypack.goнаходится package mypackи main/mypack.go(очевидно) package main.

Если вам нужны дополнительные файлы поддержки, у вас есть два варианта. Либо храните их все в корневом каталоге, либо поместите частные файлы поддержки в libподкаталог. Например

myproj/
  main/
    mypack.go
  myextras/
    someextra.go
  mypack.go
  mysupport.go

Или

myproj.org/
  lib/
    mysupport.go
    myextras/
      someextra.go
  main/
    mypack.go
  mypage.go

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

Делая так, вы получите хороший путь myproj.org/mypackдля импорта, чтобы повторно использовать код в других проектах. Если вы используете, libто внутренние файлы поддержки будут иметь путь импорта, который указывает на это myproj.org/lib/mysupport.

При создании проекта, использование main/mypack, например go build main/mypack. Если у вас есть несколько исполняемых файлов, вы также можете разделить их mainбез необходимости создавать отдельные проекты. например main/myfoo/myfoo.goи main/mybar/mybar.go.

транс
источник
14
Idomatic - это использование cmd/nameOfMyExecutableподкаталога для основного пакета (нужен только cmd/…если у вас есть несколько команд; смотрите golang.org/x/tools/cmd; в противном случае его можно поменять местами main.goна верхнем уровне). То, как вы это go installсделаете, создаст исполняемый файл «main» (или «main.exe»). Кроме того, idiomatic должен использовать internalподкаталог для внутреннего подпакета в пакете / программе, который не предназначен для использования в другом месте (ожидается, что в будущих версиях Go никто другой не будет импортировать internalпакеты, сделанные таким образом).
Дэйв С
21

Я нахожу очень полезным понять, как организовать код на Голанге в этой главе http://www.golang-book.com/11 книги, написанной Калебом Докси

EDAP
источник
13

Похоже, стандартного способа организации проектов Go не существует, но https://golang.org/doc/code.html содержит рекомендации для большинства проектов. Ответ jdi хорош, но если вы используете github или bitbucket и у вас есть дополнительные библиотеки, вы должны создать следующую структуру:

~/projects/
bin/
pkg/
src/
  github.com/
    username/
        mypack/
            foo.go
            bar.go
            mypack_test.go
        mylib/
            utillib.go
            utillib_test.go

Делая это таким образом, вы можете создать отдельный репозиторий для mylib, который может использоваться для других проектов и может быть получен с помощью «go get». Ваш проект mypack может импортировать вашу библиотеку, используя "github.com/username/mylib". Чтобы получить больше информации:

http://www.alexvictorchan.com/2014/11/06/go-project-structure/

alexdotc
источник
6

Храните файлы в одном каталоге и используйте их package mainво всех файлах.

myproj/
   your-program/
      main.go
      lib.go

Затем запустите:

~/myproj/your-program$ go build && ./your-program
Gustav
источник
1
Как это может работать? Ваш main.go должен быть основным; предположительно lib.go находится в другом пакете, тогда инструмент go жалуется, что в одной папке не может быть двух пакетов.
14
1
@ I82Much ОП спрашивает, как разделить один пакет, основную программу, на множество файлов. lib.go находится в том же пакете в этом случае.
Густав
Ах, спасибо за разъяснения.
18
@ Густав, у меня такой же вопрос. Кажется, если я помещаю пакет main в lib.go, в main.go, я не могу вызвать функции, определенные в lib.go.
Цянь Чен
@ElgsQianChen Методы должны быть открытыми, они должны начинаться с заглавной буквы. Например, MyMethod () или MyStruct {...}.
Густав
6

Давайте исследуем, как go get repository_remote_urlкоманда управляет структурой проекта $GOPATH. Если мы сделаем это, go get github.com/gohugoio/hugoон будет клонировать хранилище под

$ GOPATH / src / repository_remote / имя_пользователя / имя_проекта


$ GOPATH / src / github.com/gohugoio/hugo

Это хороший способ создать начальный путь проекта . Теперь давайте рассмотрим, какие типы проектов существуют и как организованы их внутренние структуры. Все проекты Голанга в сообществе можно отнести к категории

  • Libraries (без исполняемых двоичных файлов)
  • Single Project (содержит только 1 исполняемый файл)
  • Tooling Projects (содержит несколько исполняемых файлов)

Обычно файлы проекта golang могут быть упакованы в соответствии с любыми принципами проектирования, такими как DDD , POD

Большинство доступных проектов Go следуют этому пакетно-ориентированному дизайну

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


Библиотеки

  • Такие проекты, как драйверы баз данных , qt можно поставить под эту категорию.
  • Некоторые библиотеки, такие как color , теперь следуют плоской структуре без каких-либо других пакетов.
  • Большинство этих библиотечных проектов управляет пакетом, называемым внутренним .
  • /internal Пакет в основном используется, чтобы скрыть реализацию от других проектов.
  • Не имеет исполняемые двоичные файлы, так что нет файлов, содержащихся в основной FUNC .

 ~/$GOPATH/
    bin/
    pkg/
    src/
      repository_remote/
        user_name/
            project_name/
              internal/
              other_pkg/

Единый проект

  • Проекты , такие как Гуго , etcd имеют единственную основную FUNC в корневом уровне и.
  • Цель состоит в том, чтобы создать один единственный двоичный файл

Инструментальные проекты

  • Такие проекты, как kubernetes , go-ethereum имеют несколько основных функций , организованных в виде пакета под названием cmd
  • cmd/ Пакет управляет количеством двоичных файлов (инструментов), которые мы хотим построить

 ~/$GOPATH/
    bin/
    pkg/
    src/
      repository_remote/
        user_name/
            project_name/
              cmd/
                binary_one/
                   main.go
                binary_two/
                   main.go
                binary_three/
                   main.go
              other_pkg/
noelyahan
источник