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

时间:2012-11-03 22:15:59

标签: build go package

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

12 个答案:

答案 0 :(得分:128)

它不起作用,因为您的foobar.go源文件不在名为foobar的目录中。 go buildgo install尝试匹配目录,而不是源文件。

  1. $GOPATH设置为有效目录,例如export GOPATH="$HOME/go"
  2. foobar.go移至$GOPATH/src/foobar/foobar.go,构建工作正常。
  3. 其他建议步骤:

    1. 通过$GOPATH/bin
    2. $PATH添加到PATH="$GOPATH/bin:$PATH"
    3. main.go移至$GOPATH/src的子文件夹,例如$GOPATH/src/test
    4. go install test现在应该在$GOPATH/bin中创建一个可执行文件,可以通过在终端中键入test来调用该文件。

答案 1 :(得分:9)

编辑:既然你的意思是GOPATH,请参阅fasmatanswer(upvoted)

如“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路径用于解析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

  • 在终端机(Linux)中:
    首次运行: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.modgo.sum(删除之前的旧)

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

答案 10 :(得分:-1)

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

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

答案 11 :(得分:-1)

运行 go env -w GO111MODULE=auto 对我有用