尽管对于需要将目录与程序包名称匹配仍然是正确的答案,但是您确实需要迁移到使用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"
(我正在将VS Code与Golang扩展一起使用。)
请注意,导入路径包括了包的子目录。
处理私人回购
如果代码是私有存储库的一部分,则需要运行git命令以启用访问权限。否则,您可能会遇到其他错误本文介绍了如何针对私有Github,BitBucket和GitLab存储库执行此操作:https ://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repositories-dfe795068db4在
此还将讨论此问题:“获取”私有存储库的正确方法是什么?