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


138

即使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

我去获取github.com/adonovan/gopl.io/tree/master/ch1/helloworld时遇到了同样的问题, 原因是它没有名称为helloworld.go的文件。通过匹配软件包名称和文件名来获取作品。
keniee van

也可能是您需要升级Go。我有一个类似的问题,即我已有使用go.mod定义模块的代码。在测试机上,我下载了代码并试图对其进行编译,但Go给出了与GOPATH相关的各种错误,并且无法找到模块。这是Go版本1.7。一旦我升级了Go,它就可以正常工作了。
KyferEz

键入此终端以获取最新解释$ go help gopath
A1rPun

Answers:


161

它不起作用,因为您的foobar.go源文件不在名为的目录中foobargo 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在终端中键入来调用该可执行文件。

1
这不是错误吗?我的GOPATH=/usr/local/go-pkgsGo语言会寻找/usr/local/go-pkgs/src/<package-name>源,但go get将其放入/usr/local/go-pkgs/src/gopkg.in/<package-name>。为什么安装后我必须手动移动所有软件包?那真是愚蠢。
约西亚

3
go get通常将包裹放进去,$GOPATH/src/所以如果你打电话的go get domain.com/path/to/package话会以结尾$GOPATH/src/domain.com/path/to/package。我想您尝试从中获取软件包gopkg.in?如果是这样,那绝对是预期的行为,那么您只需使用其全名导入即可;例如,import "gopkg.in/yaml.v1"文档中所述
fasmat

1
嗯,我明白了。感谢您消除我的无知。
josiah 2015年

10

编辑:由于您的意思是GOPATH,请参阅fasmat答案(已批准)

如“ 我如何找到我的包裹? ”中所述,您需要将包裹xxx放在目录中xxx

请参阅Go语言规范

package math

共享相同文件的一组PackageName形式构成了包的实现。
一个实现可能要求包的所有源文件都驻留在同一目录中。

代码组织提到:

在构建导入软件包“ widget”的程序时,go命令将src/pkg/widget在Go根目录中查找,然后(如果在此处找不到软件包源)src/widget将按顺序在每个工作空间中搜索。

(“工作区”是您中的路径条目GOPATH:该变量可以引用多个路径以使您的“ src, bin, pkg”成为)


(原始答案)

您还应该将其设置GOPATH为〜/ go,而不是GOROOT,如“ 如何编写Go代码 ”中所示。

Go路径用于解析导入语句。它由go / build包实现并记录在文件中。

GOPATH环境变量列表地方寻找Go代码。
在Unix上,该值是用冒号分隔的字符串。
在Windows上,该值为分号分隔的字符串。
在计划9中,该值是一个列表。

不同于GOROOT

Go二进制发行版假定它们将被安装在Windows 中/usr/local/go(或c:\Go在Windows下),但是可以将它们安装在其他位置。
如果这样做,则GOROOT在使用Go工具时,需要将环境变量设置为该目录。


4
还有一个简短的视频介绍介绍了如何设置GOPATH
Ulf Holm Nielsen

1
抱歉,我已经编辑了原始问题。我到处说GOROOT的意思是 GOPATH。
米切尔·

3

TL; DR:请遵循Go约定!(经验教训很艰辛),检查旧版go并删除它们。安装最新的。

对我来说,解决方案是不同的。我在共享Linux服务器上工作,在GOPATH多次验证了我的环境变量和其他环境变量后,它仍然不起作用。我遇到了一些错误,包括“找不到包”和“无法识别的导入路径”。按照golang.org上的说明尝试使用解决方案重新安装后(包括卸载部分),仍然遇到问题。

花了我一些时间才意识到仍然有一个旧版本尚未卸载(go version然后which go再次运行... DAHH),这使我想到了这个问题并终于解决了。


2

尽管对于需要将目录与程序包名称匹配仍然是正确的答案,但是您确实需要迁移到使用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在 此还将讨论此问题:“获取”私有存储库的正确方法是什么?


-6

您是否尝试过将go的绝对目录添加到“路径”?

export PATH=$PATH:/directory/to/go/

$ PATH与go包的路径无关。
csgeek
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.