這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
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.
Proxy 伺服器
獨立開發人員或者公司都會有這樣一種需求:從某個Proxy 伺服器上更新 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.