为什么你需要使用 Go Module Proxy?
在引入 Go 模块之后,我认为我需要了解的全部事情都已经完成。我很快意识到事实并非如此。最近,人们开始提倡使用 Go 模块代理。在研究了利弊之后,我得出了结论,这是近年来最重要的变化之一。但是为什么会这样呢? 是什么使 Go 模块代理如此特别?
在 Go 模块中, 如果您添加新的依赖项或在一个缓存干净的计算机上构建Go模块,它将( go get
)根据 go.mod
下载所有依赖项并将其缓存以进行进一步的操作。您可以使用 vendor /
文件夹绕过缓存(以及下载依赖项),并构造带有 -mod = vendor
标志的 go 文件夹。
但是这两种方法都不是完美的,我们可以做得更好。
(不)使用 vendor/ folder 的问题
如果使用 vendor/
文件夹,则有一些缺点:
go
命令默认不再使用vendor/
文件夹 (在 module-aware 模式)。如果您不附加-mod = vendor
标志,它将不予以遵守。这往往会导致用户失望,并导致其他支持老版本 Go 的蹩脚解决方案出现 (看: [在 Travis CI 上使用带有供应商支持的 Go 模块](https://arslan.io/2018/08/26/using-go-modu... -与供应商在Travis-ci上的支持](https://arslan.io/2018/08/26/using-go-modu...))vendor/
文件夹, 特别是对于大型 monorepos, 占用大量空间。增加了克隆存储库所花费的时间。即使您认为克隆仅执行一次,但大多数情况下并非如此。 CI / CD 系统通常会为每个触发器克隆存储库(例如,拉取请求)。因此,从长远来看,这将导致更长的构建时间并影响团队中的每个人。- 供应新的依赖项通常会导致 难以检查 的更改。在大多数情况下,您必须将依赖项与实际的业务逻辑捆绑在一起,这使得难以进行更改。
如果你 跳过 vendor/
文件夹? 这也无济于事,因为现在您正在处理以下问题:
go
将尝试从源存储库下载依赖项。但始终存在将来任何依赖关系都可能消失的风险 (还记得左翼联盟的故事吗).- VCS 可能已关闭 (例如,github.com)。在这种情况下,您将无法再构建项目。
- 有些公司不希望在内部网络之外有任何外部连接。因此无法移除
vendor/
文件夹。 - 假设一个依赖项发布为
v1.3.0
,并且go get
获取并在本地缓存它。同时,依赖项的所有者可以通过推送具有相同标签的恶意内容来破坏存储库。如果您的 Go 模块是在一个缓存干净的计算机上重建的,那么它将使用已损坏的软件包。为了防止这种情况,您需要将go.sum
文件与go.mod
文件一起存储。 - 一些依赖项使用与
git
不同的 VCS,因此依赖于其他工具,例如hg
(Mercurial),bzr
(Bazaar) 或svn
(Subversion)。并非所有这些工具都安装在您的主机(或 Dockerfile )中,这常常导致失败。 go get
需要获取go.mod
中列出的每个依赖项的源代码,以解决传递性依赖项(它需要它们的go.mod
文件)。这极大地减慢了整个构建过程的速度,因为这意味着它必须下载(例如git clone
)每个存储库只是为了获取单个文件。
我们如何改善这种情况?
使用 Go 模块代理的优势
默认情况下,go
命令直接从 VCS 下载模块。GOPROXY
环境变量允许进一步控制下载源。环境变量将 go
命令配置为使用 Go模 块代理。
通过将 GOPROXY
环境变量设置为 Go 模块代理,可以克服上面列出的所有缺点:
- 默认情况下,Go 模块代理会缓存并永久存储所有依赖项(在不可变存储中)。这意味着您不再需要使用任何
vendor/
文件夹。 - 摆脱
vendor/
文件夹意味着您的项目将不会占用存储库中的空间。 - 由于依赖项存储在不可变的存储器中,因此即使依赖项从互联网上消失了,您也可以免受依赖。
- 一旦将 Go 模块存储在 Go 代理中,就无法覆盖或删除它。这可以保护您免受可能注入相同版本恶意代码的行为者的攻击。
- 您不再需要任何 VSC 工具来下载依赖项,因为依赖项是通过 HTTP 提供的( Go 代理在后台使用 HTTP)。
- 下载和构建Go模块的速度明显加快,因为 Go 代理通过 HTTP 分别提供了源代码(
.zip
存档)和go.mod
。与从 VCS 进行提取相比,这导致下载花费更少的时间和更快的时间(由于更少的开销)。解决依赖关系也更快,因为go.mod
可以独立获取(而之前必须获取整个存储库)。 Go 团队对其进行了测试,并发现它在快速网络速度提高了 3 倍,慢速网络速度提高了 6 倍! - 您可以轻松地运行自己的 Go 代理,这可以使您更好地控制构建管道的稳定性,并防止 VCS 停机时发生的罕见情况。
如您所见,使用 Go 模块代理对每个人都是胜利。但是我们如何使用它呢?如果您不想维护自己的 Go 模块代理怎么办?让我们研究许多替代选择。
如何使用 Go 模块代理
要开始使用 Go 模块代理,我们需要将 GOPROXY
环境变量设置为兼容的 Go 模块代理。有多种方法:
1.) 如果未设置 GOPROXY
,将其设置为空或将其设置为 direct
,则 go get
将使用与 VCS 的直接连接(例如,github。 com):
GOPROXY=""
GOPROXY=direct
也可以将其设置为 off
,这表示不允许网络使用。
GOPROXY=off
2.) 您可以开始使用公共 Go 代理。您的选择之一是使用 Go 小组(由 Google 运行)中的 Go 代理。可以在这里找到更多信息:https://proxy.golang.org/
要开始使用它,您只需设置环境变量:
GOPROXY=https://proxy.golang.org
其他公共代理有:
GOPROXY=https://goproxy.io
GOPROXY=https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
3.) 您可以运行多个开源实现并自己托管。其中一些是:
Athens
: https://github.com/gomods/athensgoproxy
: https://github.com/goproxy/goproxyTHUMBAI
: https://thumbai.app/
您需要自己维护这些。是否要通过公共互联网或内部网络提供服务,完全取决于您。
4.) 您可以购买商业产品:
Artifactory
: https://jfrog.com/artifactory/
5.) 您可以通过 file:////
URL。由于 Go 模块代理是响应 GET 请求(没有查询参数)的 Web 服务器,因此任何文件系统中的文件夹也可以用作 Go 模块代理。
即将到来的 Go v1.13 更改
Go v1.13 版本中的 Go proxy 会有一些变化,我认为应该强调:
GOPROXY
环境变量现在可以设置为以逗号分隔的列表。在回退到下一个路径之前,它将尝试第一个代理。GOPROXY
的默认值为https:///proxy.golang.org,direct
。direct
令牌之后的所有内容都将被忽略。这也意味着go get
现在将默认使用GOPROXY
。如果您根本不想使用 Go 代理,则需要将其设置为off
。- 引入了一个新的
GOPRIVATE
环境变量,该变量包含一个逗号分隔的 glob 模式列表。这可用于绕过某些路径的GOPROXY
代理,尤其是公司中的私有模块(例如:GOPRIVATE = *。internal.company.com
)。
所有这些更改表明 Go 模块代理是 Go 模块的核心和重要部分。
结论
通过公共和专用网络使用 GOPROXY
有很多优点。这是一项很棒的功能,可与 go
命令无缝配合使用。考虑到它具有许多优点(安全,快速,存储高效),明智的做法是在您的项目或组织中快速接受它。此外,Go v1.13 会默认启用它,这是改进 Go 中依赖项管理状态的另一个受欢迎的步骤。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: