为什么要使用 go module proxy
在看过 Go module
的简介之后,我以为我已经知道了这个功能我需要知道的一切。但是很快,我意识到并不是这样。最近,人们开始提倡使用 Go module proxy
。在研究了利弊之后,我得出结论,这将是近年来 Go 语言最重要
的变化之一。
但为什么会这样呢?是什么让 Go module
代理如此特别?
使用 Go modules
时,如果向干净的缓存的计算机上添加新依赖项或构建 Go module
,它将基于 go.mod
将下载(go get)所有依赖项,并将其缓存以供进一步操作。
你也可以使用 -mod=vendor
参数构建 vendor
文件夹,来绕过缓存,以及后边使用这些下载的依赖。
但以上两种方法都不完美,我们应该可以做得更好。
(不)使用 vendor 文件夹的问题
使用 vendor 文件夹的问题
-
在模块感知模式开启时,使用
go
命令,默认不再使用vendor
文件夹。如果你不附加-mod=vendor
参数,这个文件夹将不会被启用。 这通常引发问题,并导致必须使用其他陈旧的方案来支持老 Go 版本程序(请参考:在 Travis CI 上使用 Go Module 和 vendor) -
vendor
文件夹,会占用大量磁盘空间,特别是在比较大的单体应用中。这也将增加代码仓库的克隆时间。可能你认为只用克隆一次,实际却不是这样。CI/CD 在每次事件(比如:pull request
)都会触发克隆代码。因此,这将长期导致更长的编译时间,并将影响团队中的每个人。 -
使用新的依赖通常会导致难以审核代码的变化。大多数情况下,你必须将依赖项与实际的业务逻辑捆绑在一起,这导致难以进行更改。
不使用的 vendor 的问题
-
go
程序将去源码仓库下载这些依赖。总是存在任何依赖可能在将来消失的风险(记住左边的传奇故事)。 -
版本管理系统(例如
github.com
)可能关闭。在这种情况下,你将无法再次构建项目。 -
有些公司不希望内网接入外网,此时,没有
vendor
文件夹,我们将无法使用。 -
假设发布的依赖
tag
是v1.3.0
,并且已经go get
获取它到本地缓存。此时,依赖的所有者可以通过推送具有相同tag
的恶意内容来破坏代码库。如果在具有干净缓存的计算机上重建Go module
,它现在将使用被破坏的包。 为了防止这种情况,需要将go.sum
和go.mod
文件放在一起 。 -
一些依赖使用不只使用
git
作为版本管理系统
,还有可能使用hg(Mercurial)
,bzr(Bazaar
) 或svn(Subversion)
。而你的机器没有安装装或者 Dockerfile 没有配置这些工具,这都将引发问题。 -
go get
需要获取go.mod
列出的每个依赖项的源代码来解决递归依赖(需相应的go.mod
文件)。因为它意味着必须下载(例如git clone
)每个存储库以获取单个文件,这显然会使得整个构建过程变慢。
那我们怎么解决这些问题呢?
使用 go module proxy 的好处
默认情况下, go
命令会直接从版本管理系统下载代码。
GOPROXY
环境变量允许在下载源的进一步控制。配置该环境变量后,go
命令可以使用 Go module proxy
。
设置环境变量 GOPROXY
开启 Go module proxy
后,将解决上边提到的所有问题。
-
Go module proxy
默认永久缓存所有依赖(不可变存储)。这意味着,不必再使用 vendor 文件夹。 -
抛弃
vendor
文件夹,它将不会再消耗代码库的空间。 -
因为依赖项存储在
不可变存储
中,即使依赖项从网上消失,你的代码也会受到保护。 -
一旦
Go module
(依赖) 存储在Go proxy
中,就无法覆盖或删除它。这可以保护你免受可能使用相同版本注入恶意代码的攻击。 -
你不再需要任何 VSC 工具来下载依赖项,因为依赖项是通过 HTTP 获取的(
Go proxy
在后台使用 HTTP)。 -
下载和构建
Go module
的速度要快得多,因为Go proxy
通过 HTTP 独立提供源代码(.zip
存档)go.mod
。与从 VCS 获取相比,由于更少的开销,这使得下载花费更少的时间。 相比之前它必须获取整个存储库,解决依赖关系也更快,因为go.mod
可以独立获取。Go 官方团队对它进行了测试,他们看到快速网络上的速度提高了 3 倍,而慢速网络则提高了 6 倍! -
你可以轻松运行自己的
Go proxy
,这可以让你更好地控制构建管道的稳定性,并防止 VCS 关闭时的罕见情况。
如你所见,使用Go module proxy
对人人都有好处。但是我们如何使用它呢?如果你不想维护自己的Go module proxy
怎么办?这里还有许多替代方案。
如何使用 go module proxy
要开始使用Go module proxy
,我们需要将 GOPROXY
环境变量设置为兼容的Go module proxy
。这有多种方式:
-
如果没有设置
GOPROXY
,将其设置为空或设置为direct
,然后go get
将直接到VCS
(例如github.com
)拉取代码:GOPROXY="" GOPROXY=direct
GOPROXY
也可以设置为off
,这意味着不允许使用网络GOPROXY=off
-
你可以开始使用公共
GOPROXY
。你也可以选择使用 Go 官方团队的GOPROXY
(由 Google 运营)。更多信息可以在这里找到:https://proxy.golang.org/
要开始使用它,你只需设置环境变量:GOPROXY=https://proxy.golang.org
其他可用的公共代理:
GOPROXY=https://goproxy.io GOPROXY=https://goproxy.cn # proxy.golang.org 被墙了, 这个没有
-
你可以运行多个开源实现并自己托管。可用的有:
Athens
:https://github.com/gomods/athensgoproxy
:https://github.com/goproxy/goproxyTHUMBAI
:https://thumbai.app/
你既可以自己维护,也可以通过公共互联网或内部网络获取相关服务,看你自己的决定。
-
你可以购买商业产品:
Artifactory
: https://jfrog.com/artifactory/ -
你可以传入
file:///
路由。因为Go module proxy
是响应 GET 请求(没有查询参数)的 Web 服务器,所以任何文件系统中的文件夹都可以用作Go module proxy
。
Go 1.13 的变化
在 Go v1.13 版本中, Go proxy
会有一些变化,我认为应该强调一下:
- 在
GOPROXY
环境变量现在可以设置为逗号分隔的列表。它会在回到下一个路径之前尝试第一个代理。 GOPROXY
的默认值为 https://proxy.golang.org,direct。设置direct
后将忽略之后的所有内容。这也意味着go get
现在将默认使用GOPROXY
。如果你根本不想使用GOPROXY
,则需要将其设置为off
。- 新版本将引入了一个新的环境变量
GOPRIVATE
,它包含以逗号分隔的 全局列表。这可用于绕过GOPROXY
某些路径的代理,尤其是公司中的私有模块(例如:GOPRIVATE=*.internal.company.com
)。
所有这些变化都表明 Go module proxy
将是 Go module
的核心和重要组成。
总结
无论使用公共网络,还是专用网络, GOPROXY
都有很多优势。这是一个很棒的工具,它可以和 go
命令无缝协作。鉴于它具有如此多的优势(安全,快速,存储高效),明智的做法是在您的项目或组织中快速接受它。此外,在Go v1.13
版本中,默认情况下会启用它,这是另一个受欢迎的步骤,它改善了 Go 中依赖项管理的现状。
via: https://arslan.io/2019/08/02/why-you-should-use-a-go-module-proxy/
作者:Fatih Arslan 译者:TomatoAres 校对:polaris1119
- 原文作者:战神西红柿
- 原文链接:https://tomatoares.github.io/posts/go/translated/20190802-why-you-should-use-a-go-module-proxy/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。