Pull to refresh

Comments 22

Можно начинать проект с создания репозитория (на GitHub или BitBucket), тогда вопрос какую папку создать отпадает, она будет $GOPATH/src/github.com/user/project.
Можно даже репозитарий не создавать. Просто сразу ему придумать имя и создать соответствующую структуру каталогов. Потом, если надо будет, сделаете репозитарий, и все запушите.
Есть другой вариант Workspace, который тоже применяется в «быту», обычно с использованием вместе менеджеров пакетов (gpm, gopm, etc..).
Позволяет сделать в проекте подобие системы модулей.

Project
.../.godeps/… (Или любая другая папка от менеджера пакетов)
.../bin/…
.../pkg/…
.../src/moduleone
.../src/moduletwo
...main.go
Ну, имеет, конечно, право на жизнь и такой вариант — но это что обычно называют «don't fight go build system».
Не слышал о таком обычаи за проведенных мной 2 года в Go.
Почему? Это заезженная тема, по ней куча статей и топиков на golang-nuts/reddit и общая позиция (в том числе подкрепляемая официальными заявлениями Go-команды), в том, что single GOPATH — это официально поддерживаемый метод, а остальные способы активно не одобряются.
Потому что удобство первичного подхода заканчивается на втором проекте.
Обычно, чтобы не скачивать все барахло и не тащить его за собой на продакшен, применяются менеджеры пакетов, а они, как правило — применяются в той самой архитектуре, что я дал выше. Исключений не видел, либо их просто нету.

Вы можете написать, что можно составить список «go get» для себя и использовать его на продакшене, но когда речь заходит о контроле версий существующих пакетов при разработке — то он становится бесполезным.
Окей, с вашим примером, на самом деле, два момента:
1) отдельный GOPATH для отдельного проекта
2) исходники в корне GOPATH, видимо, для использования относительных путей для «модулей»

Изолированный GOPATH — с зависимостями (как с применением менеджеров пакетов, так и без) — вобщем-то, не крамольно, и для «локинга» зависимостей — даже необходимо. Но это вполне ложится на исполнение менеджерами пакетов, не обязательно выделять отдельный GOPATH для каждого проекта. Я на самом деле стараюсь не пользоваться этими менеджерами, и поддерживать код с последними версиями всех зависимых библиотек (Go-Package-Store очень помогает). Но пока еще ни разу не пришлось, собственно, «поддерживать» — все таки «обещание backward-compatibility» достаточно хорошо и на авторов библиотек распространяется, создает некую культуру.

Ну а второй момент — с выходом за src/ и относительными путями — это уж точно неодобрительная практика.

В конце концов, если вы захотите завтра ваш проект заопенсорсить, и выложить на github — придется всю эту конструкцию с отдельным GOPATH и относительными именами рефакторить и менять под корень.
Вы видимо не работали с менеджером пакетов или не с теми работали. Не могу утверждать, но таковое ощущение создалось.
Отдельных сущностей GOPATH не создается. Всегда есть команда, которая перенаправляет его на текущий проект с которым вы собираетесь работать.

«Ну а второй момент — с выходом за src/ и относительными путями — это уж точно неодобрительная практика.»

Если под «относительными путями» вы подразумеваете указание прямых директорий в импортах, то ничуть этого не происходит, из-за причины, описанной выше.
Так же, когда проект идет в опен-сорс, то он выкладывается в полном виде с приложенным файлом для конкретного менеджера пакетов, чтобы можно было собрать быстро и без боли.

И насчет — «backward-compatibility», не могу вешать никаких ярлыков, но вы живете в слишком прекрасной реальности. Я сам в своих библиотеках ломал зависимости и такое происходило во многих популярных, однако было заметно, когда очень долго пользуешься конкретной библиотекой.
не могу вешать никаких ярлыков, но вы живете в слишком прекрасной реальности

Но таки повесили ярлык :) Нет, я не питаю иллюзий и прекрасно понимаю, что это происходит время от времени, но давайте будем откровенны — бОльшая часть библиотек в Go все-таки уважают принцип обратной совместимости, и, насколько это возможно, стремятся не ломать API. Или же — пишут большими жирными буквами — «unstable. possible API break in the future» или что-то вроде.
И это я говорю о вообще любых библиотеках, мелких и никем не используемых, в том числе. Самые же основные, популярные вещи (вроде gorilla или mysql/mgo/amqp-драйверов) — стабильны, и ломать в них API не будут, 100%.

Вобщем, я не отрицаю надобность dependency менеджмента, но стараюсь не использовать. В приватных проектах, где GOPATH шерится с другими разработчиками — время от времени обновляю зависимости с помощью Go-Package-Store, и это да — можно называть «GOPATH per project», но project тут в общем смысле — на самом деле там много go-программ и все используют один общий GOPATH.

И да, я не готов спорить сейчас по теме version/dependency-менеджмента, поскольку все варианты не пробовал, но, насколько я понимаю, все эти решения создают отдельную поддиректорию вроде _vendor или .godeps и в ней хранят все зависимости, и её же используют как (второй) GOPATH. При этом делается это автоматически, без форсирования использовать какую-то нестандартную схему GOPATH.

Если кто-то напишет подробный пост с различиями существующих решений — будет отлично и познавательно.
Пардон, из-за того, что в это время работал с продакшеном — допустил ошибки.
Вместо продакшена, я имел ввиду локальное окружение, которое переносится куда нибудь в другое место или передается между разработчиками в своей команде.
Я пытался понять все это, официальную документацию читал. Но чесно говоря так и не понял, почему я не могу в любой произвольной папке создать и скомпилить программу на go. Допустим у меня есть некий проект на питоне, и вот где-то мне не хватило производительности и я решил переписать какой-то отдельный скрипт на go, почему бы мне хранить эту тулзу в внутри своего проекта. Кажется подход go предполагает, что я на любой чих буду писать какие-то универсальные тулзы или библиотеки. Но мне это не нужно. Допустим у меня есть еще другой проект в котором мне нужна аналогичная тулза с некоторыми отличиями. И вот в воркспесе go у меня появляются уже две тулзы с практически одинаковыми названиями. Тут уже придется добавлять префиксы, в каком проекте это используется.
Если у вас одиночная тулза, которая использует только стандартные либы, то проблем не должно быть. Вся эта идея с папками нужна для легкой и непринужденной установки чужих проектов и публикации своих. Запускать go build ./my_python_project/my_super_duper_tool.go вроде закон не запрещает (по крайней мере я попробовал и у меня получилось).
Нет, тулзе нужны внешние либы mgo. И возможно другие.
Как уже написали — вы можете «в любой произвольной папке создать и скомпилить программу на go».

GOPATH — это что-то вроде PYTHON_PATH, переменная, указывающая, где лежат все ваши библиотеки и исходники. То, что ваш код удобнее складывать тоже в GOPATH/src — это не обязательное требование, но естественно возникающее удобство, как только вы начинаете писать код, который а) выкладывается в open-source б) начинается использоваться в других ваших или не ваших проектах. Тогда просто нет разницы — делаете вы go get драйверу mongo или своей библиотеке.

И на самом деле GOPATH очень помогает, причем неявно, организовывать ваш код. Это просто и это удобно. С этой схемой сложно создавать хаос из исходников на компьютере. Попробуйте, и через какое-то время вы поймете, насколько это удобно. Вот тут, к примеру, один девелопер, вообще, говорит, что взял идею GOPATH на вооружение не только go-кода, но и для всего другого: mwholt.blogspot.com.es/2014/02/why-i-use-just-one-gopath.html
PYTHONPATH это другое, я его никогда не устанавливаю лишь в некоторых случаях для отладки, но и это обычно не нужно, к томуже в питоне есть vitrualenv.

go get не работает вне GOPATH.
UFO just landed and posted this here
У меня еще появилась GOROOT_BOOTSTRAP
Адепты собирающие tip из исходников думаю все прочувствовали)))
Ну, статья не для адептов )
Когда-то начал изучать Го, потом бросил, не понял как быть если я пишу две разные софтины? Мне потом менять GOPATH для второй софтины? Или Го сам понимает к какому скрипту какую зависимость прицепить при компиляции. То есть каждый новый проект в отдельную папку src/, потом через go get ставим пакеты, а потом каждый проект решает какой себе пакет взять, я правильно понял?

Подкину несколько замечаний из опыта борьбы с GOPATH кутерьмой:


  1. Если держать в GOPATH один путь, то в GOPATH/src перемешаны «свои» и «чужие» исходники и чем больше либ подключаешь, тем хуже становится.
    Можно полечить двумя путями в GOPATH, что-то типа GOPATH=/home/user/work/go-imports:/home/user/work/project-name. go get будет скачивать зависимости в первый путь, а «свои» исходники лежат по второму пути. При желании можно переносить исходники из первого во второй, чтобы поправить что-то чужое и чтобы go get не затирал изменения master-ом.


  2. GOPATH не дружит с форками. То есть как не дружит… Обычно на github-е жмёшь Fork и делаешь clone проекта своего пользователя и логично его склонировать в GOPATH/src/github.com/user/forked-repo. Бум, бах, тут-то всё и сломалось.
    Приходится применять другой алгоритм: клонировать основной проект и потом править его git remote-ы.


  3. Можно в GOPATH указывать даже 3 пути: в первый путь go get будет качать проектные зависимости, второй — глобальный, туда можно будет перемещать зависимости, чтобы несколько проектов их использовали и третий путь к директории со «своими» исходниками.


  4. Мульти-GOPATH не такая уж и страшная штука. Во-первых можно сделать env файл, которому делать source при переключении на другой проект (аля virtualenv). Во-вторых можно посмотреть в сторону менеджеров окружений, например, smartcd — помимо изменения GOPATH при переходе в директорию с проектом они дают ещё много возможностей.


Sign up to leave a comment.

Articles