As introduced in the overview post, a Go module is a collection of packages versioned as a unit, along with a go.mod file listing other required modules. The move to modules is an opportunity for us to revisit and fix many details of how the go command manages source code. The current go get model will be about ten years old when we retire it in favor of modules. We need to make sure that the module design will serve us well for the next decade. In particular:
按照前述的文章中的定义,Golang 依赖库就是带有版本的代码包,其中包括了一个 go.mod
文件,并在 go.mod
文件中列出了该代码包依赖其他包以及依赖的版本。采用 module
的方式组织 Golang 代码库让我们有机会引入一种全新的组织方式来完善 go get
和 go install
两个命令行工具的一些细节上的缺失。在新的规范应用之前,go get
和 go install
还将沿用很长时间,因此新的工具也必须保证在未来的十多年内保证可用。为此,以下这些问题尤为重要:
- 鼓励开发者为代码仓库发布代码版本,而不是直接给出
commit ID
给第三方使用。代码的版本标签意味着当前代码是可用的并且是有人维护的。同时,使用指定的 commit 仍然是支持的,虽然不建议这么做。 - 不需要使用版本控制工具(例如 bzr, fossil,git,hg,svn)也可以按照依赖库。
We want to move away from invoking version control tools such as bzr, fossil, git, hg, and svn to download source code. These fragment the ecosystem: packages developed using Bazaar or Fossil, for example, are effectively unavailable to users who cannot or choose not to install these tools. The version control tools have also been a source of exciting security problems. It would be good to move them outside the security perimeter.
We want to allow multiple modules to be developed in a single source code repository but versioned independently. While most developers will likely keep working with one module per repo, larger projects might benefit from having multiple modules in a single repo. For example, we'd like to keep golang.org/x/text a single repository but be able to version experimental new packages separately from established packages.
We want to make it easy for individuals and companies to put caching proxies in front of go get downloads, whether for availability (use a local copy to ensure the download works tomorrow) or security (vet packages before they can be used inside a company).
We want to make it possible, at some future point, to introduce a shared proxy for use by the Go community, similar in spirit to those used by Rust, Node, and other languages. At the same time, the design must work well without assuming such a proxy or registry.
We want to eliminate vendor directories. They were introduced for reproducibility and availability, but we now have better mechanisms. Reproducibility is handled by proper versioning, and availability is handled by caching proxies.
代理服务器
独立开发者或者公司都会有这样一种需求:从某个代理服务器上更新 Golang 的依赖库而不是从原始地址。这样做有些是出于网速的原因,也可能是从安全性、开源协议版本或者其他原因。按照上述两章中对 Go module 的格式和文件下载标准的定义,可以目标可以很容易的实现。当环境变量 $GOPROXY
设置非空时,vgo 将以设置的 URL
为基准获取依赖库 module
, 不再使用原有的地址。为了方便 debug ,你甚至可以将 $GOPROXY
设置成某个文件夹地址。
Proxy Servers
Both individuals and companies may prefer to download Go modules from proxy servers, whether for efficiency, availability, security, license compliance, or any other reason. Having a standard Go module format and a standard download protocol, as described in the last two sections, makes it trivial to introduce support for proxies. If the $GOPROXY environment variable is set, vgo fetches all modules from the server at the given base URL, not from their usual locations. For easy debugging, $GOPROXY can even be a file:/// URL pointing at a local tree.
We intend to write a basic proxy server that serves from vgo's own local cache, downloading new modules as needed. Sharing such a proxy among a set of computers would help reduce redundant downloads from the proxy’s users but more importantly would ensure future availability, even if the original copies disappear. The proxy will also have an option not to allow downloads of new modules. In this mode, the proxy would limit the available modules to exactly those whitelisted by the proxy administrator. Both proxy modes are frequently requested features in corporate environments.
Perhaps some day it would make sense to establish a distributed collection of proxy servers used by default in go get, to ensure module availability and fast downloads for Go developers worldwide. But not yet. Today, we are focused on making sure that go get works as well as it can without assuming any kind of central proxy servers.
The End of Vendoring
Vendor directories serve two purposes. First, they specify by their contents the exact version of the dependencies to use during go build. Second, they ensure the availability of those dependencies, even if the original copies disappear. On the other hand, vendor directories are also difficult to manage and bloat the repositories in which they appear. With the go.mod file specifying the exact version of dependencies to use during vgo build, and with proxy servers for ensuring availability, vendor directories are now almost entirely redundant. They can, however, serve one final purpose: to enable a smooth transition to the new versioned world.
When building a module, vgo (and later go) will completely ignore vendored dependencies; those dependencies will also not be included in the module's zip file. To make it possible for authors to move to vgo and go.mod while still supporting users who haven't converted, the new vgo vendor command populates a module's vendor directory with the packages users need to reproduce the vgo-based build.
What's Next?
The details here may be revised, but today's go.mod files will be understood by any future tooling. Please start tagging your packages with release tags; add go.mod files if that makes sense for your project.
The next post in the series will cover changes to the go tool command line experience.
有疑问加站长微信联系(非本文作者)