Go build:“找不到包”(即使设置了 GOPATH)

Posted

技术标签:

【中文标题】Go build:“找不到包”(即使设置了 GOPATH)【英文标题】:Go build: "Cannot find package" (even though GOPATH is set) 【发布时间】:2012-10-24 05:19:16 【问题描述】:

即使我正确设置了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

【问题讨论】:

我去github.com/adonovan/gopl.io/tree/master/ch1/helloworld时遇到了同样的问题,原因应该是它没有名为helloworld.go的文件。通过匹配包名和文件名去获取作品。 也可能是你需要升级Go。我有一个类似的问题,我有使用 go.mod 定义模块的现有代码。在一台测试机器上,我下载了代码并试图编译它,但是 Go 给了我各种与 GOPATH 相关的错误并且无法找到模块。这是 Go 版本 1.7。我升级 Go 后,它就可以正常工作了。 键入这是终端以获取最新说明$ go help gopath 【参考方案1】:

编辑:既然您指的是 GOPATH,请参阅 fasmat 的 answer(已投票)

如“How do I make go find my package?”中提到的,需要将包xxx放在目录xxx中。

见Go language spec:

package math

一组共享相同PackageName 的文件构成一个包的实现。 一个实现可能要求一个包的所有源文件位于同一个目录中。

Code organization 提到:

在构建导入包“widget”的程序时,go 命令会在 Go 根目录中查找 src/pkg/widget,然后——如果在那里找不到包源——它会搜索 src/widget 在每个工作区中按顺序排列。

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


(原答案)

您还应该将GOPATH 设置为~/go,而不是GOROOT,如“How to Write Go Code”所示。

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

GOPATH 环境变量列出了查找 Go 代码的位置。 在 Unix 上,该值是以冒号分隔的字符串。 在 Windows 上,该值是以分号分隔的字符串。 在计划 9 中,值是一个列表。

这和GOROOT不同:

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

【讨论】:

还有一个short video intro来设置GOPATH 抱歉,我已经编辑了原始问题。我到处说 GOROOT,我的意思是 GOPATH。【参考方案2】:

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

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

【讨论】:

$PATH 与你的 go 包路径无关。【参考方案3】:

它不起作用,因为您的 foobar.go 源文件不在名为 foobar 的目录中。 go buildgo 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 来调用它。

【讨论】:

这不是bug吗?我的 GOPATH=/usr/local/go-pkgs,所以 Go 在 /usr/local/go-pkgs/src/<package-name> 中查找源代码,但 go get 将其放入 /usr/local/go-pkgs/src/gopkg.in/<package-name>。为什么我必须在安装后手动移动我的所有包?这简直是​​愚蠢的。 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" 和 described in the docs。 啊,我明白了。谢谢你驱散我的无知。【参考方案4】:

TL;DR:遵循 Go 约定! (教训惨重),检查旧的 go 版本和remove 他们。安装最新版本。

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

我花了一些时间才意识到还有一个旧版本尚未卸载(运行go version 然后再次运行which go...DAHH)这让我遇到了this 的问题并最终解决了。

【讨论】:

【参考方案5】:

虽然关于需要将目录与包名匹配的公认答案仍然是正确的,但您确实需要迁移到使用 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?

【讨论】:

【参考方案6】:

我通过将 go env GO111MODULE 设置为关闭解决了这个问题

go env -w  GO111MODULE=off

注意:设置 GO111MODULE=off 将关闭最新的 GO 模块功能。

参考:Why is GO111MODULE everywhere, and everything about Go Modules (updated with Go 1.17)

GO111MODULE 与 Go 1.16

从 Go 1.16 开始,默认行为是 GO111MODULE=on,这意味着如果 你想继续使用旧的 GOPATH 方式,你将不得不强制 Go 不要使用 Go Modules 功能:

导出 GO111MODULE=off

【讨论】:

【参考方案7】:

在最近从 1.14 开始的 go 版本中,我们必须在构建或运行之前执行 go mod vendor,因为默认情况下 go 将 -mod=vendor 附加到 go 命令。 所以在做了go mod vendor之后,如果我们尝试构建,我们将不会遇到这个问题。

【讨论】:

我希望这很快就会出现在搜索结果的更高位置,因为这正是我需要知道的。 这行得通!去 v1.17 。你能详细解释一下这里到底发生了什么吗?【参考方案8】:

如果您有一个有效的$GOROOT$GOPATH,但在它们之外进行开发,如果包(您的或其他人的)尚未下载,您可能会收到此错误。

如果是这种情况,请尝试go get -d(-d 标志阻止安装)以确保在运行、构建或安装之前下载包。

【讨论】:

【参考方案9】:

跑步 go env -w GO111MODULE=auto 为我工作

【讨论】:

【参考方案10】:

对我来说,上述解决方案均无效。但是我的 go 版本不是最新的。我已经下载了最新版本并在我的mac os中替换了旧版本,之后它完美运行。

【讨论】:

【参考方案11】:

无需编辑 GOPATH 或其他任何东西,就我而言,只需执行以下操作:


/app
├── main.go
├── /utils
    └── utils.go

在需要的地方导入包。这可能不直观,因为它与 app 路径无关。您还需要在包路径中添加 app

main.go:

package main

import(
   "app/util"  
)

在 app 目录下,运行:

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.modgo.sum(删除之前的旧)

之后,使用go get github.com/example/package 解决所有依赖项,例如缺少包。

【讨论】:

以上是关于Go build:“找不到包”(即使设置了 GOPATH)的主要内容,如果未能解决你的问题,请参考以下文章

云计算找不到包

Go运行报错找不到包:package xxx is not in GOROOT

VSCode 找不到包,但 CLion 可以(CMake)

idea maven有坑之找不到依赖

Jenkins 项目找不到包;构建项目目标失败

Android Studio - 找不到与包名称“''匹配的客户端