【问题标题】:Can someone explain why GOPATH is convenient and how it should be used in general?有人能解释一下为什么 GOPATH 很方便以及它应该如何使用吗?
【发布时间】:2014-08-09 23:12:21
【问题描述】:

我是 Go 编程语言的新手,每个教程都从将 GOPATH 设置为当前项目文件夹开始。

我错过了什么吗?程序员真的应该在cd 到他的新 Go 项目文件夹时手动设置 GOPATH 吗?我已经阅读了几个关于 GOPATH 的常见问题解答条目,但仍然无法理解它。

那么为什么 GOROOT 会存在呢?它的目的是什么?

是否有任何自动工具可以检测当前目录是否为 Go 项目的根文件夹(例如通过某些隐藏文件)并自动将 GOPATH 更改为该目录?

谢谢你,任何建议真的很受欢迎

ps。例如,我开发了完全不相交的 Go 项目 A、B 和 C,他们应该生活在单一的“工作区”环境中吗?我猜不是,但是那我应该用 GOPATH 和 GOROOT 做什么呢?

【问题讨论】:

  • GOROOT 指向你的 Go 安装,GOPATH 指向你工作空间的根目录。 Go 无法通过设计自动推断这些,因此您必须设置它们。一般来说,在一个 GOPATH 中有多个项目是可以的,因为每个项目都驻留在不同的子文件夹中(按设计)。
  • 上面的评论是正确的答案,因为这个人不是在问 GOPATH 的目的是什么,而是为什么它应该在那里。

标签: go


【解决方案1】:

GOPATH 的目标是将所有包集中到一个公共工作区中。它本身并不是一个真正的新概念(例如,想想 Java 类路径),但由于不支持包版本控制,Go 的使用要简单得多。

Go 程序员在进入新项目文件夹时不应该手动设置GOPATH。每个项目文件夹本身应该是一个包,并与其他包一起位于GOPATH中,因此GOPATH应该只设置一次。教程从设置 GOPATH 开始,以便将教程工作区与其他任何内容隔离开来(或者只是假设用户尚未设置 GOPATH)。

GOROOT 设置为向 Go 程序员提供标准包,您无需对其进行任何操作。简而言之,GOROOT 有一条规则:永远不要碰它。不要在里面安装任何东西,不要修改标准包等。

我不知道有什么工具可以检测当前目录中的 Go 项目,但它的创建应该不会太复杂。

如何处理不同的项目取决于您。 Go 的方式是将每个项目作为一个包放在$GOPATH/src 目录中,然后从那里做所有事情。因为我不太喜欢它,所以我将GOPATH 定义为$HOME/.go。然后我将每个项目放在其他地方(我计算机中的任何地方)的专用目录中,并将项目目录符号链接到我的$GOPATH/src 目录中。然后我可以使用每个 Go 工具链命令(例如 go build myproject),将项目用作另一个项目的包,等等。

【讨论】:

  • 您不能“冻结”项目依赖项。 Go 的哲学是一切都应该向后兼容。如果你发布一个库,你必须确保它与旧版本的公共 API 保持兼容。如果你需要破坏 API,那么它是一个新包,应该有一个新的导入路径。要锁定一个包,常用的方法是制作一个本地副本(例如通过分叉)。
  • Go 确实支持与 Go 版本并发的有限版本控制。使用 Gox.x[.x](例如 Go1.2 或 Go1.2.2)标记提交将使 go get 始终检查与标记为 go version 列表而不是头部相同的发布的分支。它“应该”用于包含在以后的 Go 版本中添加的功能的包(例如,1.3 添加了sync.Pool),但许多包开发人员只会在 Go 版本更改时破坏 API 并滥用这一事实。
  • @dig,这在Go nuts mailing list 上通常称为“供应商”。 There's a multitude of third-party tools for doing this 以及 gopkg.in 服务是从另一个角度解决问题的替代解决方案。请务必阅读 thisthis 并在 ML 中搜索“包管理”一词。
  • @dig,简而言之,Go 目前没有包管理工具,go get 不是(一个常见的误解是将go get 视为包管理器)。有很多工具可以解决这个问题;所以你的研究,看看其中的一些,选择你最喜欢的并使用它。
  • @kostix 很高兴知道,感谢您的指导。我很困惑,因为我认为 go get 应该是 包管理器
【解决方案2】:

GOPATH 允许您在一处收集依赖源代码和生成的编译二进制文件。这似乎是一个非常有吸引力的想法。然而,我发现自己在从事几个完全不相关的 Go 项目,而另一种方法更适合我。

这与 Elwinar 的符号相似但不同。我在一个空文件夹中启动一个新项目并创建src。然后我将这个 shell 脚本放入名为 env.sh 的文件夹中:

if [ `type -p go` = "" ]; then
    export PATH=$PATH:/usr/local/go/bin
fi
export GOPATH=$PWD
export PATH=$PATH:$PWD/bin

每次开始工作,我都会使用

. env.sh

注意点和空格——它们很重要。

现在,我在这个项目上所做的一切都本地化在这个文件夹中。这可能不是最广泛使用的策略,但对我来说效果很好。

还有一件事:如果您的依赖项使用环境变量进行测试等,您也可以将它们放在env.sh 中。例如,Gorp

export GORP_TEST_DSN=test/testuser/TestPasswd9
export GO_TEST_DSN=testuser:TestPasswd9@/test

附录

在最新的 Go 版本中,GOPATH 是可选的;如果不设置,默认为 $HOME/go。如果您确实设置了它并且还想使用新的模块功能,请同时设置GO111MODULES=on

【讨论】:

  • 这看起来像我习惯的方式,我想我会选择它(因为我喜欢我的项目完全相互独立,GOPATH 优雅的“工作区”理念让我想起了那些日子我在 Apache 的 www 中有几十个“子域”文件夹,并且没有方便的方法来拆分内容而不偶尔破坏某些内容)
【解决方案3】:

您无需设置 GOPATH 或 GOROOT。默认情况下,GOPATH 位于您的用户/主目录下。

如果没有设置 GOPATH,则在 Unix 系统上假定为 $HOME/go,在 Windows 上假定为 %USERPROFILE%\go。如果您想使用自定义位置作为您的工作区,您可以设置 GOPATH 环境变量。


Go 模块

现在支持 Go 模块(从 Go 1.11 开始),因此您不必再使用 GOPATH。例如,您可以转到系统上的任何目录($GOPATH 之外),并且可以在那里初始化一个新的 Go 模块,然后开始在那里工作。不需要 GOPATH。

您只需执行一次(在目录中):

go mod init

$GOPATH:Go 将这些文件存储在它下面:

  • 源文件 ($GOPATH/src)
  • 已编译的包文件 ($GOPATH/pkg)
  • 可运行文件 ($GOPATH/bin)

$GOROOT:Go 源代码所在的位置,例如 Go 标准库。


还可以从系统上的任何位置运行任何go installed 可执行文件,您可能需要将$GOPATH/bin 添加到路径环境变量中,如下所示:

export PATH=$PATH:$(go env GOPATH)/bin

更多信息请查看this

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 2011-04-01
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    相关资源
    最近更新 更多