尽管关于需要将目录与包名称匹配的公认答案仍然是正确的,但您确实需要迁移到使用 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
与也就是说,包含您的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
当我在添加对 的引用后保存 main.go 时utils.MyFunction()
,我的 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
此处也讨论了此问题:“获取”私有存储库的正确方法是什么?