Go Modules 和 Go Proxy

Go Modules

簡介

Go 在 1.11 版本引入了新的依賴管理模式 Go Modules,旨在解決一直廣爲詬病的依賴管理問題。git

使用下列命令啓用 Go Modulesgithub

go env -w GO111MODULE=on # 不建議設爲 auto

這是持久性設定,環境變量 GOENV 指示配置文件位置。golang

Go Modules 採用語義化版本,詳見 https://semver.org/lang/zh-CN/npm

Go Modules 的使用方法詳見:json

改造一個現有的項目

場景:項目來自 GitHub,版本號做爲 tag 附着在 commit 上。bash

v0 和 v1

切換到項目文件夾,執行命令 go mods init [模塊路徑] 。注意:模塊路徑是個以 github.com 開頭的完整路徑,參考項目的 GitHub 主頁。服務器

執行命令 go build && go mod tidy ,下載依賴並整理。app

項目根目錄下會生成兩個文件(須要加入到 git 中):less

  • 文件 go.mod:指示模塊名稱、go 的版本、該模塊的依賴信息(依賴名稱),相似 npm 生成的文件 package.json
  • 文件 go.sum:該模塊的全部依賴的校驗和,相似 npm 生成的文件 package-lock.json

Go 在編譯前會下載(如需)依賴並檢查校驗和,若是不一致將拒絕編譯。dom

verifying github.com/zzc-tongji/mydictionary/v4@v4.1.0: checksum mismatch
v2+

在語義化版本的定義中,主版本號更改意味着「不兼容的 API 修改」。

對於2.0.0及以上版本,上述模塊路徑須要加上主版本號。例如:

https://github.com/zzc-tongji...

module github.com/zzc-tongji/mydictionary/v4

go 1.13

require (
    github.com/360EntSecGroup-Skylar/excelize v1.4.1
    github.com/PuerkitoBio/goquery v1.5.0
)

此時,引用模塊的地方也須要作相應的修改。例如:

https://github.com/zzc-tongji...

module github.com/zzc-tongji/mydictionary-demo/v4

go 1.13

require github.com/zzc-tongji/mydictionary/v4 v4.1.1

https://github.com/zzc-tongji...

package main

import (
    "bufio"
    "fmt"
    "os"
    "path/filepath"
    "time"

    "github.com/zzc-tongji/mydictionary/v4"
)

// ...

新建一個項目

場景:項目最終發佈到 GitHub,版本號做爲 tag 附着在 commit 上。

切換到項目文件夾,執行命令 go mods init [模塊路徑] 。注意:模塊路徑是個以 github.com 開頭的完整路徑,參考項目的 GitHub 主頁。

下載依賴模塊
  • 使用 go get [依賴模塊路徑] 下載依賴模塊的最新版本。
  • 使用 go get [依賴模塊路徑]@[版本號] 下載依賴模塊的某個版本。版本號能夠是語義化版本 vX.Y.Z,也能夠是 commit hash 。
更新模塊

編輯項目根目錄下的文件 go.mod,修改 require 部分相應行的尾部(版本號)。版本號能夠修改成語義化版本 vX.Y.Z 或 commit hash 。

清理

每次 commit 之前,使用命令 go mod tidy 修正文件 go.sum

Go Proxy

Go 在 1.13 版本加入了 Go Proxy,並提供了官方鏡像。

環境變量

相關的環境變量和默認值以下:

GOPROXY="https://proxy.golang.org,direct"
GOSUMDB="sum.golang.org"
GOPRIVATE=""
GONOPROXY=""
GONOSUMDB=""
GOPROXY

GOPROXY 指示鏡像遞增和獲取順序。每一個鏡像 URL 之間用 , 分割,按照優先順序排列。direct 表示源站。

默認值:

GOPROXY="https://proxy.golang.org,direct"

根據官方說法:

The default setting for GOPROXY is
"https://proxy.golang.org,direct", which means to try the
Go module mirror run by Google and fall back to a direct connection
if the proxy reports that it does not have the module (HTTP error 404 or 410).

因爲衆所周知的緣由,建議國內的開發者將其設爲:

GOPROXY="https://proxy.golang.org,https://goproxy.io,direct"

注意 :GOPROXY=off 表示「禁止從互聯網下載任何依賴」,GOPROXY=direct 表示「依賴一概從源站下載」。

GOSUMDB

GOSUMDB 指示校驗和服務器的地址和公鑰。對於地址 sum.golang.org ,公鑰能夠省略(內置)。

Go 在編譯前會下載(如需)依賴並檢查校驗和,若是不一致將拒絕編譯。如需關閉檢驗,設定 GOSUMDB=off

默認值:

GOSUMDB="sum.golang.org"

因爲衆所周知的緣由,建議國內的開發者將其設爲:

GOSUMDB=gosum.io+ce6e7565+AY5qEHUk/qmHc5btzW45JVoENfazw8LielDsaI+lEbq6
GOPRIVATE

GOPRIVATE 表示私域前綴。私域前綴下的全部依賴一概從源站下載,並且不作校驗。

支持多個私域前綴,每一個私域前綴之間用 , 分割。支持通配符 *

官方解釋和例子:

The GOPRIVATE environment variable controls which modules the go command considers to be private (not available publicly) and should therefore not use the proxy or checksum database. The variable is a comma-separated list of glob patterns (in the syntax of Go's path.Match) of module path prefixes. For example,

GOPRIVATE=*.corp.example.com,rsc.io/private

causes the go command to treat as private any module with a path prefix matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private, and rsc.io/private/quux.

踩坑經歷

入坑

筆者在更新 mydictionary 的時候遇到了一個問題。

  • 筆者發佈了 mydictionary v4.1.0 版本。用 mydictionary-demo 拉取這個依賴作測試。
  • 在測試過程當中發現了 mydictionary 的一處 bug 。
  • 首先,筆者修復了這個 bug 。其次,刪除了本地和遠端的 v4.1.0 標籤。而後,用 git push -f 強行修改了這個版本。最後,從新爲本地和遠端打上了 v4.1.0 標籤。
  • 當筆者再次用 mydictionary-demo 拉取這個依賴的時候,發現並無更新。
思索

筆者作了不少嘗試未果,最後發現官方鏡像 https://proxy.golang.org 上有這麼一段文字:

I removed a bad release from my repository but it still appears in the mirror, what should I do?

Whenever possible, the mirror aims to cache content in order to avoid breaking builds for people that depend on your package, so this bad release may still be available in the mirror even if it is not available at the origin. The same situation applies if you delete your entire repository. We suggest creating a new version and encouraging people to use that one instead.

對於每一個依賴的每一個語義化版本,第一次從源站獲取的數據會被官方鏡像會永久保留。也就是說,即便強行修改源站上的這個語義化版本(例如使用 git push -f),鏡像內容也不會更新。官方的建議是,棄用這個被強行修改的語義化版本,發佈一個新的語義化版本並指引人們去使用。

出坑

事實確實如此,當筆者設定 GOPROXY=direct 從源站獲取依賴,獲得的是更新後的 v4.1.0 版本。

筆者將 sum 寫入 mydictionary-demo 的文件 go.sum 中,而後將 GOPROXY 還原爲默認,最後用命令 go build 進行編譯。果真,因爲校驗和不一致,編譯停止。

# $ git clone https://github.com/zzc-tongji/mydictionary-demo
# $ cd mydictionary-demo
# $ git checkout v4.1.0

$ go build
go: downloading github.com/zzc-tongji/mydictionary/v4 v4.1.0
verifying github.com/zzc-tongji/mydictionary/v4@v4.1.0: checksum mismatch
  downloaded: h1:slMg3fcLYvE9iufNqmec2jJUojv0qnGkPsbbiBor6EA=
  go.sum:     h1:7rgn+0Pys4fw+mXiD026rTzPuHto86BRxUia8FRNQSg=

SECURITY ERROR
This download does NOT match an earlier download recorded in go.sum.
The bits may have been replaced on the origin server, or an attacker may
have intercepted the download attempt.

For more information, see 'go help module-auth'.

筆者只能按照官方的指引,發佈了一個新版本 v4.1.1 來修復這個問題。

心得

爲了不在鏡像上留下「髒數據」:

  1. 編寫測試用例並使用命令 go test 測試。
  2. 採用命令 go mod vendorgo build -mod vendor 進行本地調試。
  3. 更新版本前必定要仔細檢查,避免強制推送和重置標籤。
  4. 設定 GOPROXY=direct 繞過鏡像(前提是鏡像不會主動從源站拉去數據,官方鏡像彷佛可行)。

參考資料

go help modules

A module is a collection of related Go packages.
Modules are the unit of source code interchange and versioning.
The go command has direct support for working with modules,
including recording and resolving dependencies on other modules.
Modules replace the old GOPATH-based approach to specifying
which source files are used in a given build.

Module support

Go 1.13 includes support for Go modules. Module-aware mode is active by default
whenever a go.mod file is found in, or in a parent of, the current directory.

The quickest way to take advantage of module support is to check out your
repository, create a go.mod file (described in the next section) there, and run
go commands from within that file tree.

For more fine-grained control, Go 1.13 continues to respect
a temporary environment variable, GO111MODULE, which can be set to one
of three string values: off, on, or auto (the default).
If GO111MODULE=on, then the go command requires the use of modules,
never consulting GOPATH. We refer to this as the command
being module-aware or running in "module-aware mode".
If GO111MODULE=off, then the go command never uses
module support. Instead it looks in vendor directories and GOPATH
to find dependencies; we now refer to this as "GOPATH mode."
If GO111MODULE=auto or is unset, then the go command enables or disables
module support based on the current directory.
Module support is enabled only when the current directory contains a
go.mod file or is below a directory containing a go.mod file.

In module-aware mode, GOPATH no longer defines the meaning of imports
during a build, but it still stores downloaded dependencies (in GOPATH/pkg/mod)
and installed commands (in GOPATH/bin, unless GOBIN is set).

Defining a module

A module is defined by a tree of Go source files with a go.mod file
in the tree's root directory. The directory containing the go.mod file
is called the module root. Typically the module root will also correspond
to a source code repository root (but in general it need not).
The module is the set of all Go packages in the module root and its
subdirectories, but excluding subtrees with their own go.mod files.

The "module path" is the import path prefix corresponding to the module root.
The go.mod file defines the module path and lists the specific versions
of other modules that should be used when resolving imports during a build,
by giving their module paths and versions.

For example, this go.mod declares that the directory containing it is the root
of the module with path example.com/m, and it also declares that the module
depends on specific versions of golang.org/x/text and gopkg.in/yaml.v2:

module example.com/m

require (
    golang.org/x/text v0.3.0
    gopkg.in/yaml.v2 v2.1.0
)

The go.mod file can also specify replacements and excluded versions
that only apply when building the module directly; they are ignored
when the module is incorporated into a larger build.
For more about the go.mod file, see 'go help go.mod'.

To start a new module, simply create a go.mod file in the root of the
module's directory tree, containing only a module statement.
The 'go mod init' command can be used to do this:

go mod init example.com/m

In a project already using an existing dependency management tool like
godep, glide, or dep, 'go mod init' will also add require statements
matching the existing configuration.

Once the go.mod file exists, no additional steps are required:
go commands like 'go build', 'go test', or even 'go list' will automatically
add new dependencies as needed to satisfy imports.

The main module and the build list

The "main module" is the module containing the directory where the go command
is run. The go command finds the module root by looking for a go.mod in the
current directory, or else the current directory's parent directory,
or else the parent's parent directory, and so on.

The main module's go.mod file defines the precise set of packages available
for use by the go command, through require, replace, and exclude statements.
Dependency modules, found by following require statements, also contribute
to the definition of that set of packages, but only through their go.mod
files' require statements: any replace and exclude statements in dependency
modules are ignored. The replace and exclude statements therefore allow the
main module complete control over its own build, without also being subject
to complete control by dependencies.

The set of modules providing packages to builds is called the "build list".
The build list initially contains only the main module. Then the go command
adds to the list the exact module versions required by modules already
on the list, recursively, until there is nothing left to add to the list.
If multiple versions of a particular module are added to the list,
then at the end only the latest version (according to semantic version
ordering) is kept for use in the build.

The 'go list' command provides information about the main module
and the build list. For example:

go list -m              # print path of main module
go list -m -f={{.Dir}}  # print root directory of main module
go list -m all          # print build list

Maintaining module requirements

The go.mod file is meant to be readable and editable by both
programmers and tools. The go command itself automatically updates the go.mod file
to maintain a standard formatting and the accuracy of require statements.

Any go command that finds an unfamiliar import will look up the module
containing that import and add the latest version of that module
to go.mod automatically. In most cases, therefore, it suffices to
add an import to source code and run 'go build', 'go test', or even 'go list':
as part of analyzing the package, the go command will discover
and resolve the import and update the go.mod file.

Any go command can determine that a module requirement is
missing and must be added, even when considering only a single
package from the module. On the other hand, determining that a module requirement
is no longer necessary and can be deleted requires a full view of
all packages in the module, across all possible build configurations
(architectures, operating systems, build tags, and so on).
The 'go mod tidy' command builds that view and then
adds any missing module requirements and removes unnecessary ones.

As part of maintaining the require statements in go.mod, the go command
tracks which ones provide packages imported directly by the current module
and which ones provide packages only used indirectly by other module
dependencies. Requirements needed only for indirect uses are marked with a
"// indirect" comment in the go.mod file. Indirect requirements are
automatically removed from the go.mod file once they are implied by other
direct requirements. Indirect requirements only arise when using modules
that fail to state some of their own dependencies or when explicitly
upgrading a module's dependencies ahead of its own stated requirements.

Because of this automatic maintenance, the information in go.mod is an
up-to-date, readable description of the build.

The 'go get' command updates go.mod to change the module versions used in a
build. An upgrade of one module may imply upgrading others, and similarly a
downgrade of one module may imply downgrading others. The 'go get' command
makes these implied changes as well. If go.mod is edited directly, commands
like 'go build' or 'go list' will assume that an upgrade is intended and
automatically make any implied upgrades and update go.mod to reflect them.

The 'go mod' command provides other functionality for use in maintaining
and understanding modules and go.mod files. See 'go help mod'.

The -mod build flag provides additional control over updating and use of go.mod.

If invoked with -mod=readonly, the go command is disallowed from the implicit
automatic updating of go.mod described above. Instead, it fails when any changes
to go.mod are needed. This setting is most useful to check that go.mod does
not need updates, such as in a continuous integration and testing system.
The "go get" command remains permitted to update go.mod even with -mod=readonly,
and the "go mod" commands do not take the -mod flag (or any other build flags).

If invoked with -mod=vendor, the go command assumes that the vendor
directory holds the correct copies of dependencies and ignores
the dependency descriptions in go.mod.

Pseudo-versions

The go.mod file and the go command more generally use semantic versions as
the standard form for describing module versions, so that versions can be
compared to determine which should be considered earlier or later than another.
A module version like v1.2.3 is introduced by tagging a revision in the
underlying source repository. Untagged revisions can be referred to
using a "pseudo-version" like v0.0.0-yyyymmddhhmmss-abcdefabcdef,
where the time is the commit time in UTC and the final suffix is the prefix
of the commit hash. The time portion ensures that two pseudo-versions can
be compared to determine which happened later, the commit hash identifes
the underlying commit, and the prefix (v0.0.0- in this example) is derived from
the most recent tagged version in the commit graph before this commit.

There are three pseudo-version forms:

vX.0.0-yyyymmddhhmmss-abcdefabcdef is used when there is no earlier
versioned commit with an appropriate major version before the target commit.
(This was originally the only form, so some older go.mod files use this form
even for commits that do follow tags.)

vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef is used when the most
recent versioned commit before the target commit is vX.Y.Z-pre.

vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef is used when the most
recent versioned commit before the target commit is vX.Y.Z.

Pseudo-versions never need to be typed by hand: the go command will accept
the plain commit hash and translate it into a pseudo-version (or a tagged
version if available) automatically. This conversion is an example of a
module query.

Module queries

The go command accepts a "module query" in place of a module version
both on the command line and in the main module's go.mod file.
(After evaluating a query found in the main module's go.mod file,
the go command updates the file to replace the query with its result.)

A fully-specified semantic version, such as "v1.2.3",
evaluates to that specific version.

A semantic version prefix, such as "v1" or "v1.2",
evaluates to the latest available tagged version with that prefix.

A semantic version comparison, such as "<v1.2.3" or ">=v1.5.6",
evaluates to the available tagged version nearest to the comparison target
(the latest version for < and <=, the earliest version for > and >=).

The string "latest" matches the latest available tagged version,
or else the underlying source repository's latest untagged revision.

The string "upgrade" is like "latest", but if the module is
currently required at a later version than the version "latest"
would select (for example, a newer pre-release version), "upgrade"
will select the later version instead.

The string "patch" matches the latest available tagged version
of a module with the same major and minor version numbers as the
currently required version. If no version is currently required,
"patch" is equivalent to "latest".

A revision identifier for the underlying source repository, such as
a commit hash prefix, revision tag, or branch name, selects that
specific code revision. If the revision is also tagged with a
semantic version, the query evaluates to that semantic version.
Otherwise the query evaluates to a pseudo-version for the commit.
Note that branches and tags with names that are matched by other
query syntax cannot be selected this way. For example, the query
"v2" means the latest version starting with "v2", not the branch
named "v2".

All queries prefer release versions to pre-release versions.
For example, "<v1.2.3" will prefer to return "v1.2.2"
instead of "v1.2.3-pre1", even though "v1.2.3-pre1" is nearer
to the comparison target.

Module versions disallowed by exclude statements in the
main module's go.mod are considered unavailable and cannot
be returned by queries.

For example, these commands are all valid:

go get github.com/gorilla/mux@latest    # same (@latest is default for 'go get')
go get github.com/gorilla/mux@v1.6.2    # records v1.6.2
go get github.com/gorilla/mux@e3702bed2 # records v1.6.2
go get github.com/gorilla/mux@c856192   # records v0.0.0-20180517173623-c85619274f5d
go get github.com/gorilla/mux@master    # records current meaning of master

Module compatibility and semantic versioning

The go command requires that modules use semantic versions and expects that
the versions accurately describe compatibility: it assumes that v1.5.4 is a
backwards-compatible replacement for v1.5.3, v1.4.0, and even v1.0.0.
More generally the go command expects that packages follow the
"import compatibility rule", which says:

"If an old package and a new package have the same import path,
the new package must be backwards compatible with the old package."

Because the go command assumes the import compatibility rule,
a module definition can only set the minimum required version of one
of its dependencies: it cannot set a maximum or exclude selected versions.
Still, the import compatibility rule is not a guarantee: it may be that
v1.5.4 is buggy and not a backwards-compatible replacement for v1.5.3.
Because of this, the go command never updates from an older version
to a newer version of a module unasked.

In semantic versioning, changing the major version number indicates a lack
of backwards compatibility with earlier versions. To preserve import
compatibility, the go command requires that modules with major version v2
or later use a module path with that major version as the final element.
For example, version v2.0.0 of example.com/m must instead use module path
example.com/m/v2, and packages in that module would use that path as
their import path prefix, as in example.com/m/v2/sub/pkg. Including the
major version number in the module path and import paths in this way is
called "semantic import versioning". Pseudo-versions for modules with major
version v2 and later begin with that major version instead of v0, as in
v2.0.0-20180326061214-4fc5987536ef.

As a special case, module paths beginning with gopkg.in/ continue to use the
conventions established on that system: the major version is always present,
and it is preceded by a dot instead of a slash: gopkg.in/yaml.v1
and gopkg.in/yaml.v2, not gopkg.in/yaml and gopkg.in/yaml/v2.

The go command treats modules with different module paths as unrelated:
it makes no connection between example.com/m and example.com/m/v2.
Modules with different major versions can be used together in a build
and are kept separate by the fact that their packages use different
import paths.

In semantic versioning, major version v0 is for initial development,
indicating no expectations of stability or backwards compatibility.
Major version v0 does not appear in the module path, because those
versions are preparation for v1.0.0, and v1 does not appear in the
module path either.

Code written before the semantic import versioning convention
was introduced may use major versions v2 and later to describe
the same set of unversioned import paths as used in v0 and v1.
To accommodate such code, if a source code repository has a
v2.0.0 or later tag for a file tree with no go.mod, the version is
considered to be part of the v1 module's available versions
and is given an +incompatible suffix when converted to a module
version, as in v2.0.0+incompatible. The +incompatible tag is also
applied to pseudo-versions derived from such versions, as in
v2.0.1-0.yyyymmddhhmmss-abcdefabcdef+incompatible.

In general, having a dependency in the build list (as reported by 'go list -m all')
on a v0 version, pre-release version, pseudo-version, or +incompatible version
is an indication that problems are more likely when upgrading that
dependency, since there is no expectation of compatibility for those.

See https://research.swtch.com/vg... for more information about
semantic import versioning, and see https://semver.org/ for more about
semantic versioning.

Module code layout

For now, see https://research.swtch.com/vg... for information
about how source code in version control systems is mapped to
module file trees.

Module downloading and verification

The go command can fetch modules from a proxy or connect to source control
servers directly, according to the setting of the GOPROXY environment
variable (see 'go help env'). The default setting for GOPROXY is
"https://proxy.golang.org,direct", which means to try the
Go module mirror run by Google and fall back to a direct connection
if the proxy reports that it does not have the module (HTTP error 404 or 410).
See https://proxy.golang.org/privacy for the service's privacy policy.
If GOPROXY is set to the string "direct", downloads use a direct connection
to source control servers. Setting GOPROXY to "off" disallows downloading
modules from any source. Otherwise, GOPROXY is expected to be a comma-separated
list of the URLs of module proxies, in which case the go command will fetch
modules from those proxies. For each request, the go command tries each proxy
in sequence, only moving to the next if the current proxy returns a 404 or 410
HTTP response. The string "direct" may appear in the proxy list,
to cause a direct connection to be attempted at that point in the search.
Any proxies listed after "direct" are never consulted.

The GOPRIVATE and GONOPROXY environment variables allow bypassing
the proxy for selected modules. See 'go help module-private' for details.

No matter the source of the modules, the go command checks downloads against
known checksums, to detect unexpected changes in the content of any specific
module version from one day to the next. This check first consults the current
module's go.sum file but falls back to the Go checksum database, controlled by
the GOSUMDB and GONOSUMDB environment variables. See 'go help module-auth'
for details.

See 'go help goproxy' for details about the proxy protocol and also
the format of the cached downloaded packages.

Modules and vendoring

When using modules, the go command completely ignores vendor directories.

By default, the go command satisfies dependencies by downloading modules
from their sources and using those downloaded copies (after verification,
as described in the previous section). To allow interoperation with older
versions of Go, or to ensure that all files used for a build are stored
together in a single file tree, 'go mod vendor' creates a directory named
vendor in the root directory of the main module and stores there all the
packages from dependency modules that are needed to support builds and
tests of packages in the main module.

To build using the main module's top-level vendor directory to satisfy
dependencies (disabling use of the usual network sources and local
caches), use 'go build -mod=vendor'. Note that only the main module's
top-level vendor directory is used; vendor directories in other locations
are still ignored.

go help module-auth

The go command tries to authenticate every downloaded module,
checking that the bits downloaded for a specific module version today
match bits downloaded yesterday. This ensures repeatable builds
and detects introduction of unexpected changes, malicious or not.

In each module's root, alongside go.mod, the go command maintains
a file named go.sum containing the cryptographic checksums of the
module's dependencies.

The form of each line in go.sum is three fields:

<module> <version>[/go.mod] <hash>

Each known module version results in two lines in the go.sum file.
The first line gives the hash of the module version's file tree.
The second line appends "/go.mod" to the version and gives the hash
of only the module version's (possibly synthesized) go.mod file.
The go.mod-only hash allows downloading and authenticating a
module version's go.mod file, which is needed to compute the
dependency graph, without also downloading all the module's source code.

The hash begins with an algorithm prefix of the form "h<N>:".
The only defined algorithm prefix is "h1:", which uses SHA-256.

Module authentication failures

The go command maintains a cache of downloaded packages and computes
and records the cryptographic checksum of each package at download time.
In normal operation, the go command checks the main module's go.sum file
against these precomputed checksums instead of recomputing them on
each command invocation. The 'go mod verify' command checks that
the cached copies of module downloads still match both their recorded
checksums and the entries in go.sum.

In day-to-day development, the checksum of a given module version
should never change. Each time a dependency is used by a given main
module, the go command checks its local cached copy, freshly
downloaded or not, against the main module's go.sum. If the checksums
don't match, the go command reports the mismatch as a security error
and refuses to run the build. When this happens, proceed with caution:
code changing unexpectedly means today's build will not match
yesterday's, and the unexpected change may not be beneficial.

If the go command reports a mismatch in go.sum, the downloaded code
for the reported module version does not match the one used in a
previous build of the main module. It is important at that point
to find out what the right checksum should be, to decide whether
go.sum is wrong or the downloaded code is wrong. Usually go.sum is right:
you want to use the same code you used yesterday.

If a downloaded module is not yet included in go.sum and it is a publicly
available module, the go command consults the Go checksum database to fetch
the expected go.sum lines. If the downloaded code does not match those
lines, the go command reports the mismatch and exits. Note that the
database is not consulted for module versions already listed in go.sum.

If a go.sum mismatch is reported, it is always worth investigating why
the code downloaded today differs from what was downloaded yesterday.

The GOSUMDB environment variable identifies the name of checksum database
to use and optionally its public key and URL, as in:

GOSUMDB="sum.golang.org"
GOSUMDB="sum.golang.org+<publickey>"
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"

The go command knows the public key of sum.golang.org, and also that the name
sum.golang.google.cn (available inside mainland China) connects to the
sum.golang.org checksum database; use of any other database requires giving
the public key explicitly.
The URL defaults to "https://" followed by the database name.

GOSUMDB defaults to "sum.golang.org", the Go checksum database run by Google.
See https://sum.golang.org/privacy for the service's privacy policy.

If GOSUMDB is set to "off", or if "go get" is invoked with the -insecure flag,
the checksum database is not consulted, and all unrecognized modules are
accepted, at the cost of giving up the security guarantee of verified repeatable
downloads for all modules. A better way to bypass the checksum database
for specific modules is to use the GOPRIVATE or GONOSUMDB environment
variables. See 'go help module-private' for details.

The 'go env -w' command (see 'go help env') can be used to set these variables
for future go command invocations.

go help module-private

The go command defaults to downloading modules from the public Go module
mirror at proxy.golang.org. It also defaults to validating downloaded modules,
regardless of source, against the public Go checksum database at sum.golang.org.
These defaults work well for publicly available source code.

The GOPRIVATE environment variable controls which modules the go command
considers to be private (not available publicly) and should therefore not use the
proxy or checksum database. The variable is a comma-separated list of
glob patterns (in the syntax of Go's path.Match) of module path prefixes.
For example,

GOPRIVATE=*.corp.example.com,rsc.io/private

causes the go command to treat as private any module with a path prefix
matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private,
and rsc.io/private/quux.

The GOPRIVATE environment variable may be used by other tools as well to
identify non-public modules. For example, an editor could use GOPRIVATE
to decide whether to hyperlink a package import to a godoc.org page.

For fine-grained control over module download and validation, the GONOPROXY
and GONOSUMDB environment variables accept the same kind of glob list
and override GOPRIVATE for the specific decision of whether to use the proxy
and checksum database, respectively.

For example, if a company ran a module proxy serving private modules,
users would configure go using:

GOPRIVATE=*.corp.example.com
GOPROXY=proxy.example.com
GONOPROXY=none

This would tell the go command and other tools that modules beginning with
a corp.example.com subdomain are private but that the company proxy should
be used for downloading both public and private modules, because
GONOPROXY has been set to a pattern that won't match any modules,
overriding GOPRIVATE.

The 'go env -w' command (see 'go help env') can be used to set these variablesfor future go command invocations.

相關文章
相關標籤/搜索