47

如何从父目录进行相对导入?

来自meme/cmd/meme

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

这给出了一个模棱两可的错误:

matt@stanley:~/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

matt@stanley:~/gopath/src/bitbucket.org/anacrolix/meme/cmd/meme$ echo $GOPATH

/home/matt/gopath

如何从父目录本地导入?

4

4 回答 4

51

编辑:相对导入路径不是 Go 的方式。缺乏文档显示了相对路径的流行程度,我看不出使用它们的理由。Go 推荐的代码组织效果很好。每个包都应该有一个唯一的导入路径,并使用相同的导入路径在任何地方导入。

看看像这样的包是如何github.com/ha/doozerd/peer 导入它的邻居的。这是 Go 项目中的常见做法,我已经见过很多次了。包camlistore.org/pkg/auth(也在GitHub 上;由 Go 的主要作者之一编写)camlistore.org/pkg/netutil按完整路径导入。

即使您在同一个项目中同时拥有命令和库,这种方法也有效。在您最初的问题中,您明智地要求最佳实践。我尽力解释了有关此问题的最佳实践。


导入路径在 Go 中不能是相对的。我推荐阅读如何编写 Go 代码,这是组织 Go 项目的基本读物。这是一个简短的概述:

~/go为您的 Go 开发创建一个目录。然后说:

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

$GOPATH/src包含所有 Go 包的源代码,即使是使用go get. binpkg保留编译的输出。具有包名的包main是命令并产生可执行二进制文件,这些二进制文件转到$GOPATH/bin. 其他包是库,它们的编译目标文件放在$GOPATH/pkg.

现在如果你把你的代码放进去$GOPATH/src/matt/meme,你就可以通过import "matt/meme". 建议为您的包名称使用前缀,并为标准库保留简短的包名称。这就是为什么我使用$GOPATH/src/matt/meme而不是$GOPATH/src/meme.

围绕这个想法组织你的代码。

于 2012-05-21T15:23:24.217 回答
20

感谢您添加问题。首先是一个答案,然后是一些解释。我通过以下方式构建了您的代码

  1. 去拿,就像你拥有它一样。(我忽略了错误消息。)
  2. 如您所愿,将导入行设置main.go回“../../../meme”。
  3. (注释掉一些包含未使用变量的代码。)
  4. 然后在 meme/cmd/meme 目录中,go run main.go或者go build main.go工作。

当我说 go install 有效时,我之前的评论是错误的;我应该说去建造。

然而,关键是go build单独是行不通的。您必须键入go build main.go. 这是因为 go 命令不允许“在非本地包中进行本地导入”。你是对的,规范在这里没有什么帮助。它说,“ImportPath 的解释是依赖于实现的。” 当前的实现行为是使用CL 5787055设置的,随后在 Go-nuts 上进行了详细讨论。

“本地”表示用文件系统相对路径表示。显然,以 .. 开头的相对路径是本地的,所以诀窍就是让go命令也将 main 视为本地包。它显然在您键入时不会这样做go build,但在您键入时会这样做go build main.go

于 2012-05-22T19:29:36.280 回答
3

直接手动使用编译器、链接器等时支持相对导入。'go'(构建)工具不支持相同的(在某种程度上可与例如 Java 相媲美)。

于 2012-05-21T15:17:30.633 回答
1

这可能无法回答最初的问题,但是当我真的不需要时,我正在尝试执行上述操作,我需要做的就是go.mod暂时使用以下内容进行更新replace

module github.com/pselle/foo

replace github.com/pselle/bar => /Users/pselle/Projects/bar

require (
    github.com/pselle/bar v1.0.0
)

参考: https ://thewebivore.com/using-replace-in-go-mod-to-point-to-your-local-module/

于 2020-11-10T14:52:40.487 回答