去构建:“找不到包”(即使设置了 GOPATH)

新手上路,请多包涵

即使我正确设置了 GOPATH ,我仍然无法“开始构建”或“开始运行”以找到我自己的包。我究竟做错了什么?

 $ echo $GOROOT
/usr/local/go

$ echo $GOPATH
/home/mitchell/go

$ cat ~/main.go
package main
import "foobar"
func main() { }

$ cat /home/mitchell/go/src/foobar.go
package foobar

$ go build main.go
main.go:3:8: import "foobar": cannot find package

原文由 MitchellSalad 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

它不起作用,因为您的 foobar.go 源文件不在名为 foobar 的目录中。 go buildgo install 尝试匹配目录,而不是源文件。

  1. $GOPATH 设置为有效目录,例如 export GOPATH="$HOME/go"
  2. foobar.go 移动到 $GOPATH/src/foobar/foobar.go 并且建筑应该可以正常工作。

其他推荐步骤:

  1. 添加 $GOPATH/bin 到你的 $PATH 通过: PATH="$GOPATH/bin:$PATH"
  2. main.go 移动到 --- 的子文件夹,例如 $GOPATH/src $GOPATH/src/test
  3. go install test 现在应该在 $GOPATH/bin 中创建一个可执行文件—可以通过在终端中键入 test 来调用。

原文由 fasmat 发布,翻译遵循 CC BY-SA 3.0 许可协议

尽管关于需要将目录与包名称匹配的问题,公认的答案仍然是正确的,但您确实需要迁移到使用 Go 模块而不是使用 GOPATH。遇到这个问题的新用户可能会对使用 GOPATH 的提法感到困惑(就像我一样),这些提法现在已经过时了。因此,我将尝试解决此问题并提供与使用 Go 模块时防止此问题相关的指导。

如果您已经熟悉 Go 模块并且遇到了这个问题,请跳到下面我更具体的部分,这些部分涵盖了一些容易被忽视或忘记的 Go 约定。

本指南介绍了 Go 模块: https ://golang.org/doc/code.html

使用 Go 模块组织项目

如该文章所述,迁移到 Go 模块后,请按所述组织项目代码:

存储库包含一个或多个模块。模块是一起发布的相关 Go 包的集合。 Go 存储库通常只包含一个模块,位于存储库的根目录。一个名为 go.mod 的文件声明了模块路径:模块中所有包的导入路径前缀。该模块包含包含其 go.mod 文件的目录中的包以及该目录的子目录,直到包含另一个 go.mod 文件(如果有)的下一个子目录。

每个模块的路径不仅用作其包的导入路径前缀,而且还指示 go 命令应该在哪里下载它。例如,为了下载模块 golang.org/x/tools,go 命令将查询 https://golang.org/x/tools 指示的存储库(此处有更多描述)。

导入路径是用于导入包的字符串。一个包的导入路径是它的模块路径加上它在模块中的子目录。例如,模块 github.com/google/go-cmp 在目录 cmp/ 中包含一个包。该包的导入路径是 github.com/google/go-cmp/cmp。标准库中的包没有模块路径前缀。

您可以像这样初始化您的模块:

 $ go mod init github.com/mitchell/foo-app

您的代码无需位于 github.com 上即可构建。但是,最佳做法是按照最终将要发布的方式来构建模块。

了解尝试获取包裹时会发生什么

这里有一篇很棒的文章讨论了当您尝试获取包或模块时会发生什么: https ://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16 它讨论了包的存储位置和将帮助您理解如果您已经在使用 Go 模块,为什么会出现此错误。

确保导入的函数已经导出

请注意,如果您在从另一个文件访问函数时遇到问题,则需要确保已导出函数。如我提供的第一个链接中所述,函数必须以大写字母开头才能导出并可用于导入其他包。

目录名称

另一个关键细节(如已接受的答案中所述)是目录名称定义了包的名称。 (您的包名称需要与其目录名称相匹配。)您可以在此处查看示例: https ://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc With也就是说,包含您的 main 方法(即您的应用程序的入口点)的文件有点不受此要求的约束。

例如,当我使用这样的结构时,我的导入出现了问题:

 /my-app
├── go.mod
├── /src
   ├── main.go
   └── /utils
      └── utils.go

我无法将 utils 中的代码导入到我的 main 包中。

但是,一旦我将 main.go 放入其自己的子目录中,如下所示,我的导入工作正常:

 /my-app
├── go.mod
├── /src
   ├── /app
   |  └── main.go
   └── /utils
      └── utils.go

在该示例中,我的 go.mod 文件如下所示:

 module git.mydomain.com/path/to/repo/my-app

go 1.14

当我在添加对 utils.MyFunction() 的引用后保存 main.go 时,我的 IDE 自动提取对我的包的引用,如下所示:

 import "git.mydomain.com/path/to/repo/my-app/src/my-app"

(我正在使用带有 Golang 扩展的 VS Code。)

请注意,导入路径包括包的子目录。

处理私人回购

如果代码是私人仓库的一部分,您需要运行 git 命令来启用访问。否则,您可能会遇到其他错误本文提到了如何为私有 Github、BitBucket 和 GitLab 存储库执行此操作: https ://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repositories-dfe795068db4 这个问题也在这里讨论: What’s the proper way to “go get” a private repository?

原文由 devinbost 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题