父目录的相对导入

Mat*_*ner 41 import relative-path go

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

来自meme/cmd/meme:

import "../../../meme"
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

如何从父目录导入本地?

Mos*_*afa 48

编辑:相对导入路径不是Go的方式.缺乏文档显示了相对路径的流行程度,我没有看到使用它们的原因.Go的推荐代码组织运行良好.每个包都应具有唯一的导入路径,并使用相同的导入路径在任何位置导入.

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

即使您在同一个项目中同时拥有命令和库,这种方法也可行.在您的原始问题中,您明智地要求最佳实践.我尽力解释这方面的最佳实践.


Go中的导入路径不能相对.我建议阅读如何编写Go Code,这是组织Go项目的基本阅读材料.这是一个简短的概述:

制作一个类似~/goGo开发的目录.然后说:

$ export GOPATH=~/go
$ mkdir $GOPATH/{src,bin,pkg}
Run Code Online (Sandbox Code Playgroud)

$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.

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

  • 相对路径适用于一个(IMO关键)用例:处理分叉存储库.如果你在github上分叉某人的repo,你将不得不更新所有的import语句以引用你的副本,然后记住不要推送那些上游(或者期望上游会在合并中排除它们).只是变得草率. (12认同)
  • 虽然我理解这是组织go项目的"最佳实践"方式,但实际上它打破了通过github贡献的标准工作流程.例如,如果我分叉`github.com/ha/doozerd/peer`,克隆我的fork(`github.com/morphatic/doozerd/peer`),在邻居文件/文件夹中进行更改然后尝试运行测试,我的更改是没看到因为`import`语句是指上游回购.有没有办法解决? (3认同)
  • 我相信他们可以Mostafa,但没有记录。 (2认同)
  • 没有测试过这个,但是应该没问题:不要将你的fork下载到一个单独的目录中.将它作为远程添加到您在正确目录中的当前git repo. (2认同)
  • 在推送到 GitHub 之前,如何创建一个新项目并让这些导入行发挥作用?这里似乎存在循环依赖关系:您需要将文件放在 GitHub 上才能导入它们,但在测试它们之前不应将文件放在 GitHub 上。 (2认同)

Son*_*nia 18

感谢您添加问题.首先,答案,然后一些解释.我构建了你的代码,

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

当我说去安装工作时,我之前的评论错了; 我应该说去构建.

然而关键是go build单靠不起作用; 你必须打字go build main.go.这是因为go命令不允许"在非本地包中进行本地导入".你是对的,规格在这里没什么帮助.它狡猾地说:"ImportPath的解释依赖于实现." 当前的实现行为是使用CL 5787055设置的,随后在Go-nuts上进行了长时间的讨论.

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