Подтвердить что ты не робот

Относительный импорт из родительского каталога

Как сделать относительный импорт из родительского каталога?

От meme/cmd/meme:

import "../../../meme"

Это дает неоднозначную ошибку:

[email protected]:~/gopath/src/bitbucket.org/anacrolix/meme/cmd/meme$ go get bitbucket.org/anacrolix/meme/cmd/meme

can't load package: /home/matt/gopath/src/bitbucket.org/anacrolix/meme/cmd/meme/main.go:8:2: local import "../../../meme" in non-local package

[email protected]:~/gopath/src/bitbucket.org/anacrolix/meme/cmd/meme$ echo $GOPATH

/home/matt/gopath

Как импортировать локально из родительского каталога?

4b9b3361

Ответ 1

Спасибо, что добавил к вашему вопросу. Во-первых, ответ, затем некоторое объяснение. Я построил ваш код,

  • пойди, как и ты. (Я проигнорировал сообщения об ошибках.)
  • установка строки импорта в main.go обратно на "../../../meme", как вы хотели.
  • (комментарий немного кода, содержащего неиспользуемую переменную.)
  • то в каталоге meme/cmd/meme работало go run main.go или go build main.go.

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

Однако ключ состоит в том, что go build не работает; вы должны ввести go build main.go. Это связано с тем, что команда go не позволяет "локальный импорт в нелокальных пакетах". Вы правы, что спецификация здесь мало помогает. Это объясняет, что "интерпретация ImportPath зависит от реализации". Текущее поведение реализации было установлено с помощью CL 5787055, который впоследствии был обсуждался подробно на Go-Nuts.

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

Ответ 2

Изменить: Относительные пути импорта - это не путь Go. Отсутствие документации показывает что-то о популярности относительных путей, и я не вижу причин для их использования. Рекомендуемая организация кодов работает очень хорошо. Каждый пакет должен иметь уникальный путь импорта и импортироваться везде, используя тот же путь импорта.

Посмотрите, как пакет, например github.com/ha/doozerd/peer импортирует своих соседей. Это обычная практика среди проектов Go, и я видел ее много раз. Пакет camlistore.org/pkg/auth (также на GitHub; одним из главных авторов Go) импортирует camlistore.org/pkg/netutil по полному пути.

Даже если у вас есть обе команды и библиотеки в одном проекте, этот подход работает. В ваших первоначальных вопросах вы мудро попросили о лучших практиках. Я сделал все возможное, чтобы объяснить лучшие практики по этому вопросу.


Пути импорта не могут быть относительными в Go. Я рекомендую читать Как писать код перехода, необходимый чтение об организации проектов Go. Вот краткий обзор:

Создайте каталог, например ~/go для вашей разработки Go. Затем скажите:

$ export GOPATH=~/go
$ mkdir $GOPATH/{src,bin,pkg}

$GOPATH/src содержит исходный код для всех ваших пакетов Go, даже те, которые вы загружаете с помощью go get. bin и pkg сохранить вывод компиляций. Пакеты с именем пакета main являются командами и уступают исполняемым двоичным файлам, которые идут в $GOPATH/bin. Другие пакеты - это библиотеки, а их скомпилированные объектные файлы помещаются в $GOPATH/pkg.

Теперь, если вы поместите свой код в $GOPATH/src/matt/meme, его можно импортировать с помощью import "matt/meme". Он рекомендовал использовать префикс для имен ваших пакетов и оставить короткие имена пакетов для стандартных библиотек. Поэтому я использовал $GOPATH/src/matt/meme вместо $GOPATH/src/meme.

Организуйте свой код вокруг этой идеи.

Ответ 3

Релятивный импорт поддерживается при ручном использовании компилятора, компоновщика,... напрямую. Инструмент 'go' (build) не поддерживает то же самое (что-то сопоставимое, например, с Java).