Относительный импорт из родительского каталога
Как сделать относительный импорт из родительского каталога?
От 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
Как импортировать локально из родительского каталога?
Ответы
Ответ 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).