即使我已正确设置GOPATH
,我仍然无法获得“go build”或“go run”来查找我自己的包。我做错了什么?
$ 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
答案 0 :(得分:128)
它不起作用,因为您的foobar.go
源文件不在名为foobar
的目录中。 go build
和go install
尝试匹配目录,而不是源文件。
$GOPATH
设置为有效目录,例如export GOPATH="$HOME/go"
foobar.go
移至$GOPATH/src/foobar/foobar.go
,构建工作正常。其他建议步骤:
$GOPATH/bin
$PATH
添加到PATH="$GOPATH/bin:$PATH"
main.go
移至$GOPATH/src
的子文件夹,例如$GOPATH/src/test
go install test
现在应该在$GOPATH/bin
中创建一个可执行文件,可以通过在终端中键入test
来调用该文件。答案 1 :(得分:9)
编辑:既然你的意思是GOPATH,请参阅fasmat的answer(upvoted)
如“How do I make go find my package?”中所述,您需要将包xxx
放在目录xxx
中。
请参阅Go language spec:
package math
共享相同
PackageName
的一组文件构成了包的实现 实现可能要求包的所有源文件都位于同一目录中。
在构建导入包“
widget
”的程序时,go
命令在Go根目录中查找src/pkg/widget
,然后 - 如果找不到包源,则 - 它会按顺序在每个工作区中搜索src/widget
。
(“工作区”是GOPATH
中的路径条目:该变量可以引用“src, bin, pkg
”的多条路径
(原始答案)
您还应将GOPATH
设置为〜/ go,而不是GOROOT
,如“How to Write Go Code”中所示。
Go路径用于解析import语句。它由go / build包实现并记录。
GOPATH
环境变量列出要查找Go代码的位置 在Unix上,该值是以冒号分隔的字符串 在Windows上,该值是以分号分隔的字符串 在计划9中,值是一个列表。
这与GOROOT
:
Go二进制发行版假设它们将安装在
/usr/local/go
(或Windows下的c:\Go
)中,但可以将它们安装在其他位置。
如果执行此操作,则需要在使用Go工具时将GOROOT
环境变量设置为该目录。
答案 2 :(得分:6)
尽管对于需要将目录与程序包名称匹配仍然是正确的答案,但是您确实需要迁移到使用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
在添加对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?
答案 3 :(得分:4)
在从1.14开始的最新go版本中,我们必须在构建或运行之前执行go mod vendor
,因为默认情况下,go会将-mod=vendor
附加到go命令中。
因此,在完成go mod vendor
之后,如果我们尝试构建,就不会遇到这个问题。
答案 4 :(得分:3)
TL; DR:遵循Go惯例! (课程学到了很多方法),检查旧版本和remove版本。安装最新版本。
对我而言,解决方案是不同的。我在共享的Linux服务器上工作,在多次验证我的GOPATH
和其他环境变量之后,它仍然无效。我遇到了几个错误,包括'找不到包'和'无法识别的导入路径'。尝试按照this(包括golang.org部分)上的说明重新安装uninstall解决方案后仍然遇到问题。
我花了一些时间才意识到还有一个尚未卸载的旧版本(再次运行go version
然后which go
...... DAHH)让我遇到this个问题终于解决了。
答案 5 :(得分:1)
我通过将go env GO111MODULE设置为关闭来解决了这个问题
go env -w GO111MODULE=off
答案 6 :(得分:0)
如果您拥有有效的$GOROOT
和$GOPATH
,但在它们之外进行开发,则如果未下载软件包(您或他人的软件包),则可能会收到此错误。
在这种情况下,请尝试运行go get -d
(-d标志阻止安装),以确保在运行,构建或安装之前已下载软件包。
答案 7 :(得分:0)
要无需安装就可以找到您项目的软件包(这在开发过程中很常见),只需将项目路径附加到GOPATH
。
GOPATH=$GOPATH:/path/to/project
go run main.go
应该能够从项目本身中找到软件包。Mac
类似;对于Windows
,分隔符为;
,而不是:
。Goland
中:Settings
-> Go
-> GOPATH
,在Project GOPATH
下,添加项目路径。Goland
应该能够在开发过程中从项目本身中找到软件包。答案 8 :(得分:0)
对我来说,上述解决方案均无效。但是我的 go 版本不是最新的。我已经下载了最新版本并在我的 mac os 中替换了旧版本,之后它运行良好。
答案 9 :(得分:0)
无需编辑 GOPATH 或任何其他内容,就我而言,只需执行以下操作:
/app
├── main.go
├── /utils
└── utils.go
在需要的地方导入包。这可能不直观,因为它与 app 路径无关。您还需要在包路径中添加应用:
main.go
:
package main
import(
"app/util"
)
在应用程序目录中,运行:
go mod init app
go get <package/xxx>
go build main.go
/ go run main.go
你应该没事了。
GOPATH = /home/go
appPath = /home/projects/app
用 go mod init app
创建一个合适的 go.mod 和 go.sum(删除之前的旧)
之后,使用 go get github.com/example/package
解决所有依赖项,例如丢失的包。
答案 10 :(得分:-1)
您是否尝试将 go 的绝对目录添加到“路径”?
export PATH=$PATH:/directory/to/go/
答案 11 :(得分:-1)
运行 go env -w GO111MODULE=auto
对我有用