【翻譯】Command Go (下)

File types(文件類型)

go命令檢查目錄中特定文件的集合橄仍。它根據(jù)文件的擴展名表示要檢查的文件纱新。這些擴展名是:

.go
        Go source files.
.c, .h
        C source files.
        If the package uses cgo or SWIG, these will be compiled with the
        OS-native compiler (typically gcc); otherwise they will
        trigger an error.
.cc, .cpp, .cxx, .hh, .hpp, .hxx
        C++ source files. Only useful with cgo or SWIG, and always
        compiled with the OS-native compiler.
.m
        Objective-C source files. Only useful with cgo, and always
        compiled with the OS-native compiler.
.s, .S
        Assembler source files.
        If the package uses cgo or SWIG, these will be assembled with the
        OS-native assembler (typically gcc (sic)); otherwise they
        will be assembled with the Go assembler.
.swig, .swigcxx
        SWIG definition files.
.syso
        System object files.

除.syso之外的每個類型的文件都可能包含構(gòu)建約束霹肝,但是go命令會停止掃描文件中第一個不是空行或//樣式行注釋的構(gòu)建約束。有關(guān)更多詳細信息次绘,請參閱go / build包文檔。
通過Go 1.12版本,非測試Go源文件還可以包含// go:binary-only-package注釋邮偎,指示包源僅包含在文檔中管跺,不得用于構(gòu)建包二進制文件。這樣就可以單獨以編譯形式分發(fā)Go包禾进。即使是僅二進制包也需要準確的導入塊來列出所需的依賴關(guān)系豁跑,以便在鏈接生成的命令時可以提供這些依賴關(guān)系。請注意泻云,此功能計劃在Go 1.12發(fā)布后刪除艇拍。

The go.mod file

模塊版本由源文件樹定義,其根目錄中包含go.mod文件宠纯。當運行g(shù)o命令時卸夕,它會查找當前目錄,然后依次查找父目錄征椒,找到go.mod以確定當前模塊的模塊跟娇哆。

go.mod文件是面向行的,可以使用“//”注釋勃救,而不能用"/* */ " 注釋碍讨,每行有一個指令,由一個動詞接一個參數(shù)組成蒙秒,例如:

module my/thing
go 1.12
require other/thing v1.0.2
require new/thing/v2 v2.3.4
exclude old/thing v1.2.3
replace bad/thing v1.4.5 => good/thing v1.4.5

動詞指令包含:

module, to define the module path;
go, to set the expected language version;
require, to require a particular module at a given version or later;
exclude, to exclude a particular module version from use; and
replace, to replace a module version with a different module version.

exclude勃黍, replace只適用于主模塊中的go.mod。當作為依賴項的時候被忽略晕讲。更多細節(jié)參閱https://research.swtch.com/vgo-mvs

前導的動詞可以從相鄰行中分解出來覆获,創(chuàng)建一個模塊,就像Go 的 import 語句一樣瓢省。

require (
        new/thing v2.3.4
        old/thing v1.2.3
)

go.mod文件的設(shè)計既可以直接編輯弄息,也可以通過工具輕松更新。'go mod edit'命令可用于從程序和工具中解析和編輯go.mod文件勤婚。請參閱'go help mod edit'摹量。

go命令每次使用模塊圖時都會自動更新go.mod,以確保go.mod始終準確地反映現(xiàn)實并且格式正確馒胆。例如缨称,考慮這個go.mod文件:

module M
require (
        A v1
        B v1.0.0
        C v1.0.0
        D v1.2.3
        E dev
)
exclude D v1.2.3

更新將將非規(guī)范的版本標識重寫為semver格式,因此 A的v1變?yōu)?v1.0.0祝迂,E的dev變?yōu)槠鋎ev分支上最新提交的偽版本號睦尽,可能是 v0.0.0-20180523231146-b3f5c0f6e5f1.

更新操作 修改require需求已滿足 exclude 排除指令。因此 對于被排除的 D v1.2.3的需求將被更新到下一個可用版本型雳,也許是 D v1.2.4 or D v1.3.0.

更新消除冗余或誤導性的require需求当凡。例如 A v1.0.0本身需要B v1.2.0和C v1.0.0.而go.mod 中對B v1.0.0的需求是
具有誤導性的(由于A需求B v1.2.0代替)山害,并且它的需求C v1.0.0是冗余的(M與A模塊都需要C v1.0.0)因此兩者都將被刪除。如果模塊M包含直接從B或C導入的包宁玫,則將保留需求粗恢,但更新為正在使用的版本。

最后欧瘪,更新以規(guī)范化格式(canonical formatting)重新格式化go.mod眷射,一遍將來機器修改將導致最小的差異。

因為模塊試圖定義導入語句的含義佛掖,所以加載包的任何命令都會更新go.mod文件妖碉,包括go build, go get, go install, go list, go test, go mod graph, go mod tidy, and go mod why.

GOPATH environment variable

Go path 英語接續(xù)import語句,它由 go/build 包實現(xiàn)并記錄芥被。
(譯注:以下內(nèi)容可能與Go1.11支持Go Modules后不符欧宜,故不作翻譯)
The GOPATH environment variable lists places to look for Go code. On Unix, the value is a colon-separated string. On Windows, the value is a semicolon-separated string. On Plan 9, the value is a list.

If the environment variable is unset, GOPATH defaults to a subdirectory named "go" in the user's home directory ($HOME/go on Unix, %USERPROFILE%\go on Windows), unless that directory holds a Go distribution. Run "go env GOPATH" to see the current GOPATH.

See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH.

Each directory listed in GOPATH must have a prescribed structure:

The src directory holds source code. The path below src determines the import path or executable name.

The pkg directory holds installed package objects. As in the Go tree, each target operating system and architecture pair has its own subdirectory of pkg (pkg/GOOS_GOARCH).

If DIR is a directory listed in the GOPATH, a package with source in DIR/src/foo/bar can be imported as "foo/bar" and has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".

The bin directory holds compiled commands. Each command is named for its source directory, but only the final element, not the entire path. That is, the command with source in DIR/src/foo/quux is installed into DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped so that you can add DIR/bin to your PATH to get at the installed commands. If the GOBIN environment variable is set, commands are installed to the directory it names instead of DIR/bin. GOBIN must be an absolute path.

Here's an example directory layout:GOPATH=/home/user/go

/home/user/go/
    src/
        foo/
            bar/               (go code in package bar)
                x.go
            quux/              (go code in package main)
                y.go
    bin/
        quux                   (installed command)
    pkg/
        linux_amd64/
            foo/
                bar.a          (installed package object)

Go searches each directory listed in GOPATH to find source code, but new packages are always downloaded into the first directory in the list.See https://golang.org/doc/code.html for an example.

GOPATH and Modules

當使用modules時,GOPATH不在用于解決導入問題拴魄,然而它依舊用于存放下載的源碼(GOPATH/pkg/mod)和編譯后的課執(zhí)行文件

Internal Directories(內(nèi)部路徑)

在一個名為"internal"的目錄或子目錄下編寫的代碼冗茸,只能被其所在父目錄根節(jié)點下的代碼引用。以下是示例:

/home/user/go/
    src/
        crash/
            bang/              (go code in package bang)
                b.go
        foo/                   (go code in package foo)
            f.go
            bar/               (go code in package bar)
                x.go
            internal/
                baz/           (go code in package baz)
                    z.go
            quux/              (go code in package main)
                y.go

z.go被引用時的導入路徑是"foo/internal/baz"匹中,不過這樣的導入只能用于foo根節(jié)點下的源文件(foo/bar/x.go 與 foo/quux/y.go)夏漱,另一個$GOPATH/src下的項目crash無法導入。
(譯注:go 命令源碼中cmd目錄下的compile, go, link等目錄下都包含了 internal目錄顶捷。以及testdata目錄用于存放測試數(shù)據(jù))

Vendor Directories

Go1.6支持用本地的依賴副本來導入依賴挂绰,使用Vendoring來實現(xiàn)。在"vendor"目錄下的代碼只能被其父節(jié)點的根目錄下的文件引用服赎,且導入路徑只要從vendor算起葵蒂,省略vendor與之前的路徑。下面例子在上一節(jié)的基礎(chǔ)上加了"vendor"的內(nèi)部目錄重虑,新增一個"oo/vendor/crash/bang"目錄践付。

/home/user/go/
    src/
        crash/
            bang/              (go code in package bang)
                b.go
        foo/                   (go code in package foo)
            f.go
            bar/               (go code in package bar)
                x.go
            vendor/
                crash/
                    bang/      (go code in package bang)
                        b.go
                baz/           (go code in package baz)
                    z.go
            quux/              (go code in package main)
                y.go

在內(nèi)部路徑vendor下可見性規(guī)則以上節(jié)一致。不過z.go中的代碼被導入時的路徑為"baz"而不是"/foo/vendor/bar"缺厉,如前文所述永高,vendor以及之前的路徑被省略了。
vendor目錄中的代碼是外部src/crash的復制芽死,在foo/vendor下的源文件中乏梁,"crash/bang"導入路徑引用的是"foo/vendor/crash/bang"而不是高層級的那個目錄次洼。
導入路徑檢查不包括在vendor目錄下的項目关贵。
當"go get"檢出或升級git倉儲,現(xiàn)在也會更新 submodules卖毁。
Vendor目錄不影響使用"go get"檢出的代碼倉儲(go get檢出的代碼總是在GOPATH中)揖曾。

總結(jié) 路徑導入時落萎,先查找項目下的vendor目錄,然后是GOPATH炭剪,最后是GOROOT

Module proxy protocol(模塊代理協(xié)議)

go命令默認從版本控制系統(tǒng)直接下載模塊练链,正如“go get”一樣,GOPROXY 環(huán)境變量允許對源碼下載的進一步控制奴拦。 如果 GOPROXY未設(shè)置媒鼓,或者是空字符串或者設(shè)置為“direct”字符串,下載使用默認的連接到版本控制系統(tǒng)错妖。將GOPROXY設(shè)置為“off”不允許從任何源下載代碼绿鸣。否則,GOPROXY應(yīng)該是模塊代理的 URL暂氯,在這種情況下潮模,go命令將從該代理獲取所有模塊。無論從哪下載模塊痴施,下載的模塊必須與go.sum中的條目匹配擎厢。(有關(guān)驗證的討論,請參閱“go help modules”)

go模塊代理可以是相應(yīng)GET請求的任何Web服務(wù)器辣吃。請求沒有查詢參數(shù)动遭,因此即使是從固定文件系統(tǒng)(包括 file:///URL)提供的服務(wù)站點也可以是模塊代理。

可以發(fā)送到Go模塊代理的GET請求是:

GET $ GOPROXY / <module> / @ v / list返回給定模塊的所有已知版本的列表齿尽,每行一個沽损。
GET $ GOPROXY / <module> / @ v / <version> .info返回有關(guān)給定模塊的該版本的JSON格式的元數(shù)據(jù)。
GET $ GOPROXY / <module> / @ v / <version> .mod返回給定模塊的該版本的go.mod文件循头。
GET $ GOPROXY / <module> / @ v / <version> .zip返回給定模塊的該版本的zip存檔绵估。

為避免在區(qū)分大小寫的文件系統(tǒng)中提供的服務(wù)出問題,<module> <version> 元素是case-encoded的卡骂,把每個大寫字母轉(zhuǎn)換為一個感嘆號接一個對應(yīng)的小寫字母:github.com/Azure 被編碼為 github.com/!azure

給定模塊的JSON格式的元數(shù)據(jù)對應(yīng)以下GO結(jié)構(gòu)體国裳,可能在將來進行擴展

type Info struct {
    Version string    // version string
    Time    time.Time // commit time
}

給定模塊的特定版本的zip存檔是標準zip文件,其包含與模塊的源代碼和相關(guān)文件對應(yīng)的文件樹全跨。存檔使用斜杠分隔的路徑缝左,存檔中的每個文件路徑必須以<module> @ <version> /開頭,其中模塊和版本直接替換浓若,而不是大小寫編碼渺杉。模塊文件樹的根對應(yīng)于存檔中的<module> @ <version> /前綴。

即使直接從版本控制系統(tǒng)下載挪钓,go命令也會合成顯式的info是越,mod和zip文件,并將它們存儲在本地緩存中碌上,GOPATH / pkg / mod / cache / download倚评,就像直接使用代理下載一樣浦徊。緩存布局與代理URL空間相同,因此在(或復制到)https://example.com/proxy上提供 GOPATH / pkg / mod / cache / download 會讓其他用戶訪問這些緩存的模塊版本天梧,通過設(shè)置 GOPROXY = https://example.com/proxy盔性。

Import path syntax(路徑導入語法)

路徑導入語句指明了一個存儲在本地文件系統(tǒng)中的包∧馗冢總之冕香,導入語句表示導入了標準庫中的包(如"unicode/utf8")或在工作目錄(GOPATH)下的包。

Relative import paths(相對路徑)

以 ./ 或 ../開頭的路徑被稱為相對路徑后豫,go工具鏈有兩種方式支持相對路徑暂筝。

  1. 相對路徑可以被用于命令行中,如果你在導入路徑為"unicode"的工作目錄下硬贯,想對"unicode/utf8"運行測試焕襟,可以使用"go test ./utf8",而不需要再給出絕對路徑饭豹。
    類似的當你在"unicode/utf8"目錄下執(zhí)行"go test .."將對“unicode”進行測試鸵赖。相對模式匹配(Relative patterns)也是可以的“go test ./..”將對當前路線下的所有子目錄進行測試。
  2. 如果我們要編譯運行的Go程序不在工作空間$GOPATH下拄衰,我們可以在導入語句中使用相對路徑它褪,導入那些同樣不在工作空間中的源碼。(已測試翘悉,結(jié)合Vendor Directories總結(jié)理解)
    這使得我們在工作空間外進行多個小程序包的實驗時變得方便茫打,但是類似的不在GOPATH中的程序不能被“go install”安裝(因為找不到安裝的地方),所以每次運行他們時都會編譯妖混。(譯注:親測在Go1.12中是可以的老赤,GOPATH外部的項目go install 后,在GOPATH/bin下生成.exe文件)
    為避免歧義制市,在GOPATH中不允許使用相對路徑抬旺。(To avoid ambiguity, Go programs cannot use relative import paths within a work space.經(jīng)測試是可以,不懂這里是啥意思)

Remote import paths

某些導入路徑還描述了如何從版本控制系統(tǒng)獲得程序包的源代碼祥楣。

一些常見的代碼托管站點具有特殊語法:

Bitbucket (Git, Mercurial)

        import "bitbucket.org/user/project"
        import "bitbucket.org/user/project/sub/directory"

GitHub (Git)

        import "github.com/user/project"
        import "github.com/user/project/sub/directory"

Launchpad (Bazaar)

        import "launchpad.net/project"
        import "launchpad.net/project/series"
        import "launchpad.net/project/series/sub/directory"

        import "launchpad.net/~user/project/branch"
        import "launchpad.net/~user/project/branch/sub/directory"

IBM DevOps Services (Git)

        import "hub.jazz.net/git/user/project"
        import "hub.jazz.net/git/user/project/sub/directory"

對于托管在其他服務(wù)器上的代碼开财,導入路徑可用使用版本控制類型進行限定,或者go tool 可以通過 https/http 動態(tài)獲取導入路徑误褪,并從HTML中的<meta>標記中發(fā)現(xiàn)代碼所在位置责鳍。

聲明代碼位置,表單的導入路徑

repository.vcs/path

使用指定的版本控制系統(tǒng)指定具有或沒有.vcs后綴的給定倉儲兽间,然后指定該倉儲中的路徑历葛。支持的版本控制系統(tǒng)是:

Bazaar      .bzr
Fossil      .fossil
Git         .git
Mercurial   .hg
Subversion  .svn

例如:

import "example.org/user/foo.hg"

表示 Mercurial 倉儲的根路徑在 example.org/user/foo 或 foo.hg

import "example.org/repo.git/foo/bar"

表示 Git 類型倉儲的 foo/bar 目錄在 example.org/repo 或 repo.git.

當一個版本控制系統(tǒng)支持多種協(xié)議,下載時一次嘗試每種協(xié)議渡八。例如啃洋,Git下載時嘗試 https:// 然后是 git + ssh://

默認情況下,下載僅限于已知的的安全協(xié)議(如 https, ssh)要覆蓋Git下載的此設(shè)置屎鳍,可以設(shè)置
GIT_ALLOW_PROTOCOL 環(huán)境變量(有關(guān)詳細信息宏娄,請參閱:“go help environment”)。

如果導入路徑不是一直的代碼托管站點且缺少版本控制限定符逮壁,go tool 嘗試通過https/http 獲取導入孵坚,并在 document文檔HTML <head>中查找<meta>標記。

meta 標記格式如下

<meta name="go-import" content="import-prefix vcs repo-root">

導入路徑的前綴對應(yīng)倉儲的根目錄窥淆。它必須是使用“go get”獲取的包的前綴或者完全匹配卖宠。如果它不是完全匹配,則在前綴處發(fā)出另一個http請求以驗證<meta>標記是否匹配忧饭。

meta標記應(yīng)該盡可能早的出現(xiàn)在文件中扛伍。特別是,它應(yīng)該出現(xiàn)在任何原生 JavaScript 或 CSS之前词裤,避免混淆Go命令的限制解析器刺洒。

vcs 包含 "bzr", "fossil", "git", "hg", "svn".

repo-root 是版本控制系統(tǒng)的根,包含 scheme 且不包含 .vcs 修飾符

例如:

import "example.org/pkg/foo"

將得到以下請求:

https://example.org/pkg/foo?go-get=1 (preferred)
http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure)

如果該頁面包含以下meta標記

<meta name="go-import" content="example.org git https://code.org/r/p/exproj">

go 工具將驗證 https://example.org/?go-get=1 是否包含相同的meta標記然后調(diào)用 git clone 克隆 https://code.org/r/p/exproj 到本地的 GOPATH/src/example.org 路徑.

當使用GOPATH模式時吼砂,下載的包存放在環(huán)境變量GOPATH列表第一個路徑下逆航。

當使用modules模式時,下載的包存放在模塊緩存(譯注:GOPATH/pkg/mod/cache)渔肩。(參見'go help module-get'和'go help goproxy'因俐。)

使用模塊時,將識別一個額外go-import 元標記周偎,并優(yōu)先于那些列出的版本控制系統(tǒng)抹剩。該變體(variant)使用“mod”作為內(nèi)容值中的vcs,如:

<meta name="go-import" content="example.org mod https://code.org/moduleproxy">

此標記表示從 URL=https://code.org/moduleproxy的代理上提供的模板代理獲取以 example.org 開頭的路徑模塊蓉坎。
有關(guān)代理協(xié)議的詳細信息吧兔,請參閱“go help goproxy”。

Import path checking(導入路徑檢查)

當上述慣用導入路徑功能重定向得到已知代碼托管站點時袍嬉,每個得到的包郵兩種可能的導入路徑境蔼,使用自定義域或者已知的托管站點。

如果package聲明語句緊跟著(換行前)以下兩種形式之一的注釋伺通,則成包語句具有“導入注釋”(“import comment”)

package math // import "path"
package math /* import "path" */

go 命令將拒絕一個有導入注釋的安裝包箍土,,除非引用該包的導入路徑罐监。通過這種方式吴藻,導入注釋讓包的作者確保使用自定義導入路徑而不是直接指向底層的代碼托管路徑。

導入路徑檢查在帶有vendor目錄樹的代碼中失效弓柱,這允許復制代碼到本地的vendor目錄沟堡,而不需要更改導入注釋侧但。

使用模塊時也會禁用導入路徑檢查。導入注釋被go.mod文件中的module語句淘汰航罗。

Modules, module versions, and more

模塊是一系列g(shù)o依賴包的集合禀横。模塊是源碼交換與版本控制的單元。go命令對模塊有直接的支持粥血,包括記錄和分析對其他模塊的支持柏锄。模塊取代了之前用GOPATH來指定哪些源文件需要被編譯。

Preliminary module support(模塊預支持)

Go1.11包含了對模塊的預支持复亏,包括一個新的可以感知模塊(module-aware)的“go get”命令趾娃。對模塊支持將會持續(xù)改進,這期間將保持兼容性直到官方宣布缔御,然后在晚些時候官方將移除項目必須在GOPATH的特性抬闷,以及對舊的“go get”命令的支持。

體驗Go1.11模塊支持最快的方法是將你的代碼倉儲檢出到GOPATH/src外耕突,在倉儲中創(chuàng)建go.mod文件(下一節(jié)介紹)饶氏,然后對改倉儲下的文件執(zhí)行g(shù)o命令。

為了更好的控制有勾,Go1.11的模塊支持一個臨時的環(huán)境變量GO111MODULE疹启,有三個不同的字符串值:off, on, auto(默認)對應(yīng)三種模式:off 表示不使用新的模塊支持,仍然從vendor與GOPATH查找依賴蔼卡;我們稱為“GOPATH mode”喊崖。on表示使用模塊支持,不會查詢GOPATH雇逞,我們稱之為模塊感知或運行與“模塊感知模式(module-aware mode)”荤懂,auto或未設(shè)置環(huán)境變量,是否啟用模塊支持取決于當前文件目錄塘砸。只有當前倉儲在GOPATH/src外且包含go.mod文件或在包含go.mod文件的目錄下节仿。

在模塊感知模式下,GOPATH不再是定義編譯(build)時的導入路徑掉蔬,但仍然會保存下載的依賴包廊宪,以及安裝(install)的可執(zhí)行文件(在GOPATH/bin中,除非設(shè)置了GOBIN環(huán)境變量)

Defining a module(定義模塊)

通過在go源文件文件樹的根目錄創(chuàng)建go.mod可以定義模塊女轿,包含go.mod的目錄成為模塊根(module root)箭启,一般情況下,模塊跟也是代碼倉儲的根目錄(非必須)蛉迹。模塊包含模塊根下所有Go packages集合以及它們的子目錄傅寡,但不包括那些本身擁有g(shù)o.mod的文件。

模塊路徑(module path)是與模塊跟一直的導入路徑前綴。go.mod文件定義模塊路徑荐操,通過給模塊與版本號芜抒,定義了編譯時需要導入的模塊的指定版本。

下面go.mod文件表示它是“example.com/m”這個模塊的模塊根托启,而且還定義了該模塊依賴特定版本的golang.org/x/text 與 gopkg.in/yaml.v2

module example.com/m

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

當對模塊直接編譯時宅倒,go.mod文件可以指定替換和排除(replacements and excluded)版本,但是當模塊被內(nèi)嵌在更大的模塊中編譯時將會忽略它們驾中。更多關(guān)于go.mod文件的細節(jié)參見:'go help go.mod'

要開始一個新模塊,'go mod init'命令可以用來在模塊的根目錄創(chuàng)建一個go.mod文件模聋,包含一個簡單的模塊聲明肩民。

go mod init example.com/m

在一個已經(jīng)有依賴管理工具(godep,glide链方,dep)的項目中g(shù)o mod init命令也會為其添加合適的配置持痰。

一旦go.mod文件被創(chuàng)建,不需要額外的步驟祟蚀,類似'go build','go test'甚至'go list'都會自動添加新的依賴來滿足導入工窍。

The main module and the build list(主模塊,編譯列表)

主模塊(main module)是go命令執(zhí)行的模塊前酿,go命令先在當前目錄下查找模塊根患雏,然后順著父目錄依次查找。

通過require罢维,replace淹仑,exclude關(guān)鍵字,主模塊的go.mod文件精確的定義了go命令所需的包(packages)集合肺孵,依賴模塊提供的包只能通過require定義匀借,replace與exculd語句將被忽略。因此replace與exculd語句允許主模塊對自身編譯的完全控制平窘,而不受到依賴的影響吓肋。

編譯列表“build list”提供的包的模塊的集合,編譯列表最開始只包含主模塊瑰艘,隨后go命令遞歸的將編譯列表中模塊依賴的模塊添加進來是鬼,直到?jīng)]有依賴的模塊。如果包含一個模塊的多個版本紫新,最后只保留最新的版本(根據(jù)語義版本排序)屑咳。

go list 命令提供了主模塊與編譯列表的信息:

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(模塊維護)

go.mod文件意味著它可以被程序與工具閱讀,維護弊琴。go命令行會自動更新go.mod文件兆龙,使其保持標準格式以及require語句的準確。

當go命令發(fā)現(xiàn)未知的導入語句時,都會查找包含當前導入的模塊紫皇,并自動將最新版本添加到go.mod文件慰安。因此,大部分情況下只要在源碼中添加導入語句聪铺,然后運行'go build','go test'或者'go list'化焕,go命令中分析包的部分會解析導入語句,更新go.mod文件铃剔。

任何go命令都可以發(fā)現(xiàn)必須添加的缺失模塊撒桨,及時只引用到模塊中的一個包(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)。另一方面键兜,確定一個模塊不再需要凤类,且可以刪除,需要查看模塊中所有的包普气,包括所有可能的構(gòu)建配置(體系結(jié)構(gòu)谜疤,操作系統(tǒng),構(gòu)建標簽等)现诀∫目模“go mod tidy”命令建立該視圖,然后添加需要的模塊仔沿,移除不需要的模塊坐桩。

作為gp.mod文件中維護require語句的部分,go命令追蹤哪些些包被當前模塊直接引入封锉,哪些包只是被其它模塊間接依賴撕攒。僅被間接依賴的包在go.mod文件中會被"http:// indirect"注釋標記,一旦間接引用被直接導入烘浦,go.mod文件中的間接需求將被刪除抖坪。間接的模塊需求只有以下情況會出現(xiàn):聲明他們自己的依賴失敗,或者升級模塊依賴闷叉。(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.)

因為這種自動維護擦俐,go.mod文件中的信息總是最新的,可讀的構(gòu)建描述握侧。

“go test”命令更新go.mod文件以更改構(gòu)建中使用的模塊版本蚯瞧。一個模塊的升級意味著其它模塊的升級(版本升級),同樣的品擎,一個模塊的降級可能意味著其它模塊的降級埋合。“go get”命令同樣會做這樣的隱式改變萄传。如果go.mod文件被直接編輯甚颂,“go build”,“go list”會假定升級是有意的,并自動進行隱式升級振诬,這樣的升級會通過更新go.mod反映出來蹭睡。

"go mod"命令提供了在維護中使用的其他功能了解模塊和go.mod文件。請參見"go help mod".

-mod 構(gòu)建標識為更新和使用go.mod提供了額外的控制

如果使用-mod=readonly 命令標識赶么,上述的對go.mod的自動隱式升級將不被允許肩豁,相反,當需要改變go.mod時會失敗辫呻。這個設(shè)置在檢查go.mod文件是否需要升級時很有用清钥,例如在持續(xù)集成和測試系統(tǒng)。即使使用-mod=readonly標識放闺,“go get”命令依然可以更新go.mod文件祟昭,并且“go mod”命令不接受-mod標識(或者其他標識)

如果使用-mod=vendor,go命令假定vendor目錄有正確的依賴副本雄人,且忽略go.mod文件中的依賴从橘。

Pseudo-versions(假版本)

go.mod文件一級go命令一般使用語義化版本作為標準格式來描述模塊的版本念赶,所以我們可以比較兩個版本哪個是新版本的哪個是舊的版本础钠。類似v1.2.3這樣的版本標識引進于源碼倉儲中的版本標簽。未加標簽的版本可以使用“假版本”叉谜,類似“v0.0.0-yyyymmddhhmmss-abcdefabcdef”UTC時間前綴旗吁,而后綴則是最后提交的哈希前綴。時間確保了兩個假版本之間可以進行前后比較停局,提交哈虾艿觯可以精確定位到某一次提交,本例中的v0.0.0前綴董栽,可以推出距提交最近的一個標簽码倦。

有三種假版本的格式:

  • vX.0.0-yyyymmddhhmmss-abcdefabcdef 被用在目標提交之前沒有更早的版本提交。(這是最初唯一的格式锭碳,因此在一些舊的go.mod文件中使用這個格式袁稽,即使提交是帶標簽的。)
  • vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef 當目標提交之前的最新版本提交是vX.Y.Z-pre時
  • vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef 當目標提交之前的最新版本提交是vX.Y.Z時
    “假版本”不需要手動鍵入擒抛,go命令接收原提交哈希推汽,自動轉(zhuǎn)換成假版本(或者使用標簽)。這個轉(zhuǎn)換是模塊查詢的例子歧沪。

Module queries(模塊查詢)

go命令接受在 命令行與主模塊的go.mod文件中使用“模塊查詢”替換確切的模塊版本歹撒。(在主模塊的go.mod文件執(zhí)行查詢后,go命令使用查詢結(jié)果更新文件)

  • 一個完整確切的語義化版本:v1.2.3诊胞,指定一個特定的版本暖夭。
  • 語義化版本前綴:v1 或 v1.2,指定該前綴的最新版本。
  • 語義化版本比較:"<v1.2.3"或者">=1.5.6"鳞尔,指定最接近給定版本的特定版本嬉橙。(<,<=對應(yīng)最新版本,>,>=對應(yīng)最老版本)
  • 字符串“l(fā)atest”匹配可獲得的最新的版本標簽寥假,或者源碼倉儲中最新的未加標簽版本市框。
  • 特定的版本標識,例如提交前綴糕韧,標簽版本枫振,分支名稱,選擇特定的代碼版本萤彩。如果版本標識有語義化版本標簽粪滤,查詢指定那個語義化版本。否則查詢指定提交的假版本雀扶。

所有的查詢將優(yōu)先考慮發(fā)布版本而非預發(fā)布版本杖小。例如:“<v1.2.3”將返回“v1.2.2”而不是"v1.2.3-pre1",盡管"v1.2.3-pre1"更接近給定的查詢目標愚墓。

在主模塊go.mod中被exclude語句排除的版本予权,將無法通過模塊查詢獲得。

下面的例子都是可以的:

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(模塊兼容于語義化版本控制)

go命令要求模塊使用語義化版本控制浪册,并期望版本能準確的表示兼容性:它假定v1.5.4版本向下兼容v1.5.3扫腺,v1.4.0甚至v1.0.0 。更一般的說村象,go命令期望包遵循“導入兼容原則(import compatibility rule)”:

“如果一個舊的包與一個新的包郵相同的導入路徑笆环,那么新包必須向下兼容舊的包『裾撸”

因為Go命令假定導入兼容規(guī)則躁劣,對模塊的需求只能設(shè)置所依賴的最小需求版本:不能設(shè)置最大版本或者排除指定版本。但是兼容性規(guī)則并不能保證:v1.5.4可能是錯誤的库菲,而不是向后兼容 v1.5.3的替代品账忘。因此,go 命令永遠不會從舊版本主動更新未要求的模塊的新版本蝙昙。

在語義化版本控制中闪萄,改變主版本意味著缺少對更早版本的兼容。為確保導入兼容奇颠,go 命令要求模塊的主版本在v2以上的使用主版本作為模塊路徑的最后一個元素败去。例如,example.com/m的v2.0.0版必須使用模塊路徑example.com/m/v2烈拒,該模塊中的包將使用該路徑作為其導入路徑前綴圆裕,如example.com/m/v2 /sub/ PKG广鳍。以這種方式包括模塊路徑中的主要版本號和導入路徑稱為“語義導入版本控制(semantic import versioning)”。主要版本為v2及更高版本的模塊的偽版本以該主版本而非v0開頭吓妆,如v2.0.0-20180326061214-4fc5987536ef赊时。

作為一種特殊情況,以gopkg.in/開頭的模塊路徑繼續(xù)使用在該系統(tǒng)上建立的約定:主要版本始終存在行拢,并且前面有一個點而不是斜杠:gopkg.in/yaml.v1和gopkg.in/yaml.v2祖秒,而不是gopkg.in/yaml和gopkg.in/yaml/v2。

go命令將具有不同模塊路徑的模塊視為不相關(guān):它認為 example.com/m和example.com/m/v2之間沒有任何聯(lián)系舟奠。具有不同主要版本的模塊可以在一次構(gòu)建中一起使用议双,并且由于它們的包使用不同的導入路徑而保持獨立嚼贡。

在語義版本控制中克饶,主要版本v0用于初始開發(fā)帮掉,表示沒有期望穩(wěn)定性或向后兼容性。主要版本v0沒有出現(xiàn)在模塊路徑中耿戚,因為這些版本是為v1.0.0做準備湿故,并且v1也沒有出現(xiàn)在模塊路徑中。

在使用語義化版本控制之前編寫的代碼膜蛔,可以使用主版本v2或者更高版本來描述與v0和v1一樣未版本化的導入路徑坛猪。
為了適應(yīng)這樣的代碼,如果源代碼存儲庫對于沒有g(shù)o.mod的文件樹具有v2.0.0或更高版本的標記飞几,則該版本被認為是v1模塊的可用版本的一部分砚哆,并且在轉(zhuǎn)換時被賦予+incompatible的后綴到模塊版本独撇,如在v2.0.0 +incompatible 屑墨。+incompatible標記也適用于從此類版本派生的偽版本,如v2.0.1-0.yyyymmddhhmmss-abcdefabcdef +incompatible纷铣。

總之卵史,構(gòu)建列表中有類似v0版本,預發(fā)布版本搜立,假版本或"+incompatible"這些依賴('go list -m all' 記錄的)表明當升級依賴的時候會存在問題以躯,由于上述那些版本沒有考慮版本兼容。

Module code layout

現(xiàn)在啄踊,參閱 https://research.swtch.com/vgo-module 查看更多關(guān)于版本控制系統(tǒng)的代碼如何映射到模塊文件樹忧设。

Module downloading and verification

go命令維護著主模塊中與go.mod文件一起的一個名為go.sum的文件,該文件包含對指定模塊版本的預期加密校驗碼颠通。每次用到一個依賴時址晕,會將校驗碼添加到go.sum中(如果不存在),或者匹配當前存在的現(xiàn)有條目顿锰。

go命令維護緩存下載的包谨垃,并在每個包下載的時候計算和記錄它們的加密校驗碼启搂。在正常操作中,go命令根據(jù)主模塊的go.sum文件檢查那些預計算的校驗碼刘陶,而不是每次命令調(diào)用都計算它們胳赌。“go mod verify”命令檢查下載的模塊復制緩存是否仍然匹配它們的校驗碼記錄與go.sum中的條目匹配匙隔。(譯注-疑問:每次調(diào)用go命令時疑苫,會拿go.sum與什么校驗?)

通過設(shè)置GOPROXY環(huán)境變量纷责,go命令可以通過代理獲取模塊缀匕,而不是直接連接到源版本控制系統(tǒng)。

有關(guān)代理的詳細信息以及緩存的已下載軟件包的格式碰逸,請參閱“go help goproxy”乡小。

Modules and vendoring

當使用模塊時,go命令完全忽略vendor目錄饵史。

默認情況下满钟,go命令從源(版本控制系統(tǒng))下載模塊并使用他們的副本以滿足依賴(在驗證后)。為了允許與舊版本Go進行交互操作胳喷,或者要確保構(gòu)建需要的所有文件存在同一個文件樹下湃番,“go mod vendor”在主模塊根目錄下創(chuàng)建名為vendor的目錄,在該目錄下存儲所有構(gòu)建與測試依賴的所有包吭露。

要使用主模塊頂層vendor目錄來滿足構(gòu)建依賴(不使用網(wǎng)絡(luò)源和本地緩存)吠撮,使用命令“go build -mod=vendor”。注意只使用主模塊最頂層的vendor目錄讲竿,其它位置的vendor依然被忽略泥兰。

Module-award go get(模塊感知的go get)

“go get”命令會根據(jù)當前處于模塊感知模式或者傳統(tǒng)的 GOPATH 模式來改變行為。即使在傳統(tǒng)GOPATH模式下题禀,此幫助文檔也可以通過“go help module-get”訪問鞋诗,它描述了“go get”在模塊感知模式下運行機制。

用法:

go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages]

解析并添加依賴到當前開發(fā)的模塊迈嘹,然后構(gòu)建削彬,安裝它們。

第一步是解析要添加哪個依賴項秀仲。

對于每個指定的包或者包模式融痛,get 必須決定要使用哪個版本對應(yīng)的模塊。默認情況下神僵,get選擇最新的發(fā)布版本標簽雁刷,如: v0.4.5 或 v1.2.3.如果沒有發(fā)布版本標簽,get選擇最新的預發(fā)布版本標簽挑豌,如 v0.0.1-pre1 安券。如果根本就沒有版本標簽墩崩,get 選擇最新的一次提交作為下載的版本。

當在包參數(shù)添加@version后綴時侯勉,默認版本選擇會被覆蓋鹦筹,像“go ger golang.org/x/text@v0.3.0”。對于存儲在版本倉儲中的模塊址貌,version 后綴還可以是提交的哈希值铐拐,分支標識,或者其他源控制系統(tǒng)能識別的語法练对,就像'go get golang.org/x/text@master'. 版本后綴@latest 作為默認的后綴遍蟋,它的效果就像上文提到的下載最新版本。

如果考慮的一個模塊已經(jīng)在當前開發(fā)模塊的依賴中螟凭,那么get將更新需求的版本虚青。可以允許指定一個更早的版本來進行模塊降級螺男。版本后綴 @none 表明依賴的條目將被移除棒厘,降級或者移除模塊取決于需求。

雖然默認使用包含命名包的模塊的最新版本下隧,但它不使用該模塊的最新版本的依賴項奢人。相反,它更喜歡使用該模塊請求的特定依賴版本淆院。例如何乎,如果最新的A需要模塊B v1.2.3,而B v1.2.4和v1.3.1也可用土辩,那么'go get A'將使用最新的A但是然后使用B v1.2.3支救,按照A的要求。(如果對特定模塊有沖突的需求脯燃,那么'go get'通過獲取其中最大請求版本來解決這些需求搂妻。)

-u 標記指導 go get 命令將依賴模塊更新到最新的次版本號與修訂號(不是主版本號)蒙保,繼續(xù)前面的例子辕棚,“go get -u A”將使得A使用最新的B v1.3.1(不是B v1.2.3)(譯注:語義化版本的格式:v主版本號.次版本號.修訂號 -> v major.minor.patch)

-u=path 標記(不是 -u path)指導get更新可得的最新修訂號依賴,繼續(xù)上述例子邓厕,“go get -u=path A”將使用B v1.2.4(不是B v1.2.3)

總之逝嚎,添加一個新的依賴,可能需要更細現(xiàn)有的依賴详恼,以滿足繼續(xù)編譯补君,go get 自動執(zhí)行此操作。同樣對模塊降級引起其他模塊降級時昧互,go get也將自動執(zhí)行操作挽铁。

在解析伟桅,升級和降級模塊以及更新go.mod之后,-m標志指示get停在這里叽掘。使用-m時楣铁,每個指定的包路徑也必須是模塊路徑,而不是模塊根目錄下的包的導入路徑更扁。

-insecure標志允許從存儲庫中提取并使用不安全的方案(如HTTP)解析自定義域盖腕。謹慎使用。

第二步是下載(若需要)構(gòu)建和安裝指定包

如果參數(shù)指定一個模塊而不是一個包(因為在模塊的根目錄下沒有Go源碼)浓镜,則跳過該參數(shù)的安裝步驟而不會報錯溃列。例如'go get golang.org/x/perf' 依舊會成功,即使在該導入路徑下沒有相應(yīng)的代碼

注意允許使用包名的模式匹配膛薛,并在解析模塊版本后進行擴展听隐。例如'go get golang.org/x/perf/cmd/...' 添加最新的 golang.org/x/perf 然后在最新版本安裝命令

-d 標記指示get命令下載構(gòu)建指定包所需的源碼,包括下載需要的依賴哄啄,但是不執(zhí)行構(gòu)建和安裝遵绰。

如果沒有指定 package參數(shù),“go get”將應(yīng)用于主模塊增淹,并應(yīng)用于當前目錄下的Go包(如果有)椿访。特別的,“go get -u”與 "go get -u=patch" 更新主模塊的所有依賴虑润。沒有package參數(shù)和 -u 參數(shù)成玫,“go get”相當于“go install”,“go get -d”相當于“go list”

有關(guān)模塊的更多信息拳喻,請參閱“go help modules”哭当。

有關(guān)指定包的更多信息,請參閱“go help packages”冗澈。

本文描述了使用模塊來管理源代碼和依賴關(guān)系的行為钦勘。如果go命令在GOPATH模式下運行,則get的標志和效果的細節(jié)會發(fā)生變化亚亲,就像'go help get'一樣彻采。請參閱'go help modules'和'go help gopath-get'。

另見:go build捌归,go install肛响,go clean,go mod惜索。

Package lists and patterns(包列表與模式匹配)

許多命令應(yīng)用于一組包的集合:

go action [packages]

通常特笋,[packages]是導入路徑列表。

導入路徑是根路徑或以 '.' 或 '..' 元素開頭的路徑被理解問文件系統(tǒng)路徑巾兆,表示包在那個路徑下猎物。

否則虎囚,導入路徑 P 表示該包在路徑 DIR/src/P 下,其中DIR是GOPATH環(huán)境變量的其中之一蔫磨。

如果未指定路徑溜宽,那么指令 action 將應(yīng)用于當前目錄的包。

路徑有四個保留名稱质帅,不應(yīng)該用于使用go tool 構(gòu)建的包:

-"main"表示獨立可執(zhí)行文件中的頂級包适揉。
-"all"擴展到所有GOPATH樹中的所有包。例如煤惩,'go list all'列出本地系統(tǒng)上的所有軟件包嫉嘀。使用模塊時,“all”擴展到主模塊中的所有包及其依賴項魄揉,包括任何測試所需的依賴項剪侮。

  • “std”就像 all 一樣, 不過擴展到標準Go庫中的包。
  • “cmd”擴展為Go存儲庫的命令及其內(nèi)部庫洛退。

以“cmd/”開頭的導入路徑僅匹配Go倉儲中的源碼瓣俯。

導入路徑模式可以包含一個或多個“...”通配符,每個通配符匹配任意字符串兵怯,包括空字符串和包含斜杠的字符串彩匕。這樣的模式匹配擴展到GOPATH樹種的所有包目錄,查找與模式匹配的名稱媒区。

為了使模式匹配更方便驼仪,有兩種特殊情況:首先在模式匹配的末尾添加 "/..." 可以匹配空字符串,因此 net/... 同時匹配 net 包以及它的所有子包袜漩,如 net/http绪爸。 其次,任何以斜杠分割的模式元素通配符都不會參與與vendored包路徑中“vendor”元素的匹配宙攻。所以奠货,“./...”不會匹配子目錄中的 "./vendor" 或 "./mycode/vendor" 包,而是匹配 "./vendor/..." 和 "./mycode/vendor/..."座掘。 然而递惋,注意命名為“vendor”路徑本身包含源代碼時,不算一個 vendored 包:cmd/vendor 是名為vendor 的命令雹顺,會被模式 "cmd/..." 匹配丹墨。有關(guān)vendoring的更多信息,請參閱golang.org/s/go15vendor嬉愧。

導入路徑還可以命名要從遠程存儲庫下載的包。運行'go help importpath'了解詳細信息喉前。

程序中的每個包都必須具有唯一的導入路徑没酣。按照慣例王财,這是通過使用屬于你的唯一前綴啟動每個路徑來實現(xiàn)的。例如裕便,Google內(nèi)部使用的路徑都以“google”開頭绒净,而表示遠程存儲庫的路徑則以代碼的路徑開頭,例如“github.com/user/repo”偿衰。

程序中的包名不需要具有唯一性挂疆,但有兩個具有特殊含義的保留包名。名稱main表示命令(源碼)下翎,而不是庫(源碼)缤言。命令將被構(gòu)建為二進制文件,無法導入视事。名稱“documentation”表示目錄中非Go程序的文檔胆萧。go命令會忽略該包中的文件。

作為一種特殊情況俐东,如果包列表是來自單個目錄的.go文件列表跌穗,則該命令將應(yīng)用于由這些文件組成的單個合成包,忽略任何構(gòu)建約束并忽略目錄中的任何其他文件虏辫。

以“.”或“_”開頭的目錄和文件名將被go工具忽略蚌吸,如“testdata”目錄一樣。

Testing flags

“go test”命令接受適用于它自身的標記和適用于test結(jié)果二進制文件的標記砌庄。

幾個標記控制性能分析并生成適合“go tool pprof”的執(zhí)行配置文件套利。執(zhí)行"go tool pprof -h"獲取更多信息。
pprof的 --alloc_space, --alloc_objects, --show_bytes 選項控制如何顯示信息鹤耍。

“go test”識別下面的標記并控制任何測試的執(zhí)行:

-bench regexp
    Run only those benchmarks matching a regular expression.
    By default, no benchmarks are run.
    To run all benchmarks, use '-bench .' or '-bench=.'.
    The regular expression is split by unbracketed slash (/)
    characters into a sequence of regular expressions, and each
    part of a benchmark's identifier must match the corresponding
    element in the sequence, if any. Possible parents of matches
    are run with b.N=1 to identify sub-benchmarks. For example,
    given -bench=X/Y, top-level benchmarks matching X are run
    with b.N=1 to find any sub-benchmarks matching Y, which are
    then run in full.

-benchtime t
    Run enough iterations of each benchmark to take t, specified
    as a time.Duration (for example, -benchtime 1h30s).
    The default is 1 second (1s).
    The special syntax Nx means to run the benchmark N times
    (for example, -benchtime 100x).

-count n
    Run each test and benchmark n times (default 1).
    If -cpu is set, run n times for each GOMAXPROCS value.
    Examples are always run once.

-cover
    Enable coverage analysis.
    Note that because coverage works by annotating the source
    code before compilation, compilation and test failures with
    coverage enabled may report line numbers that don't correspond
    to the original sources.

-covermode set,count,atomic
    Set the mode for coverage analysis for the package[s]
    being tested. The default is "set" unless -race is enabled,
    in which case it is "atomic".
    The values:
        set: bool: does this statement run?
        count: int: how many times does this statement run?
        atomic: int: count, but correct in multithreaded tests;
                significantly more expensive.
    Sets -cover.

-coverpkg pattern1,pattern2,pattern3
    Apply coverage analysis in each test to packages matching the patterns.
    The default is for each test to analyze only the package being tested.
    See 'go help packages' for a description of package patterns.
    Sets -cover.

-cpu 1,2,4
    Specify a list of GOMAXPROCS values for which the tests or
    benchmarks should be executed. The default is the current value
    of GOMAXPROCS.

-failfast
    Do not start new tests after the first test failure.

-list regexp
    List tests, benchmarks, or examples matching the regular expression.
    No tests, benchmarks or examples will be run. This will only
    list top-level tests. No subtest or subbenchmarks will be shown.

-parallel n
    Allow parallel execution of test functions that call t.Parallel.
    The value of this flag is the maximum number of tests to run
    simultaneously; by default, it is set to the value of GOMAXPROCS.
    Note that -parallel only applies within a single test binary.
    The 'go test' command may run tests for different packages
    in parallel as well, according to the setting of the -p flag
    (see 'go help build').

-run regexp
    Run only those tests and examples matching the regular expression.
    For tests, the regular expression is split by unbracketed slash (/)
    characters into a sequence of regular expressions, and each part
    of a test's identifier must match the corresponding element in
    the sequence, if any. Note that possible parents of matches are
    run too, so that -run=X/Y matches and runs and reports the result
    of all tests matching X, even those without sub-tests matching Y,
    because it must run them to look for those sub-tests.

-short
    Tell long-running tests to shorten their run time.
    It is off by default but set during all.bash so that installing
    the Go tree can run a sanity check but not spend time running
    exhaustive tests.

-timeout d
    If a test binary runs longer than duration d, panic.
    If d is 0, the timeout is disabled.
    The default is 10 minutes (10m).

-v
    Verbose output: log all tests as they are run. Also print all
    text from Log and Logf calls even if the test succeeds.

-vet list
    Configure the invocation of "go vet" during "go test"
    to use the comma-separated list of vet checks.
    If list is empty, "go test" runs "go vet" with a curated list of
    checks believed to be always worth addressing.
    If list is "off", "go test" does not run "go vet" at all.

一下標記同樣可以被“go test”識別肉迫,并可用于執(zhí)行期間對測試進行分析:

-benchmem
    Print memory allocation statistics for benchmarks.

-blockprofile block.out
    Write a goroutine blocking profile to the specified file
    when all tests are complete.
    Writes test binary as -c would.

-blockprofilerate n
    Control the detail provided in goroutine blocking profiles by
    calling runtime.SetBlockProfileRate with n.
    See 'go doc runtime.SetBlockProfileRate'.
    The profiler aims to sample, on average, one blocking event every
    n nanoseconds the program spends blocked. By default,
    if -test.blockprofile is set without this flag, all blocking events
    are recorded, equivalent to -test.blockprofilerate=1.

-coverprofile cover.out
    Write a coverage profile to the file after all tests have passed.
    Sets -cover.

-cpuprofile cpu.out
    Write a CPU profile to the specified file before exiting.
    Writes test binary as -c would.

-memprofile mem.out
    Write an allocation profile to the file after all tests have passed.
    Writes test binary as -c would.

-memprofilerate n
    Enable more precise (and expensive) memory allocation profiles by
    setting runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
    To profile all memory allocations, use -test.memprofilerate=1.

-mutexprofile mutex.out
    Write a mutex contention profile to the specified file
    when all tests are complete.
    Writes test binary as -c would.

-mutexprofilefraction n
    Sample 1 in n stack traces of goroutines holding a
    contended mutex.

-outputdir directory
    Place output files from profiling in the specified directory,
    by default the directory in which "go test" is running.

-trace trace.out
    Write an execution trace to the specified file before exiting.

Each of these flags is also recognized with an optional 'test.' prefix, as in -test.v. When invoking the generated test binary (the result of 'go test -c') directly, however, the prefix is mandatory.

The 'go test' command rewrites or removes recognized flags, as appropriate, both before and after the optional package list, before invoking the test binary.

For instance, the command

go test -v -myflag testdata -cpuprofile=prof.out -x
will compile the test binary and then run it as

pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out
(The -x flag is removed because it applies only to the go command's execution, not to the test itself.)

The test flags that generate profiles (other than for coverage) also leave the test binary in pkg.test for use when analyzing the profiles.

When 'go test' runs a test binary, it does so from within the corresponding package's source code directory. Depending on the test, it may be necessary to do the same when invoking a generated test binary directly.

The command-line package list, if present, must appear before any flag not known to the go test command. Continuing the example above, the package list would have to appear before -myflag, but could appear on either side of -v.

When 'go test' runs in package list mode, 'go test' caches successful package test results to avoid unnecessary repeated running of tests. To disable test caching, use any test flag or argument other than the cacheable flags. The idiomatic way to disable test caching explicitly is to use -count=1.

To keep an argument for a test binary from being interpreted as a known flag or a package name, use -args (see 'go help test') which passes the remainder of the command line through to the test binary uninterpreted and unaltered.

For instance, the command

go test -v -args -x -v
will compile the test binary and then run it as

pkg.test -test.v -x -v
Similarly,

go test -args math
will compile the test binary and then run it as

pkg.test math
In the first example, the -x and the second -v are passed through to the test binary unchanged and with no effect on the go command itself. In the second example, the argument math is passed through to the test binary, instead of being interpreted as the package list.

Testing functions

"go test" 命令期望在與之對應(yīng)的" * _test.go " 中找到test, benchmark, and example方法。

test function 命名為 TestXxx(Xxx不能以小寫字母開頭)且應(yīng)該有以下方法簽名:

func TestXxx(t *testing.T) { ... }

benchmark function 命名為 BenchmarkXxx 且方法簽名格式如下:

func BenchmarkXxx(b *testing.B) { ... }

example 方法與 test方法相似稿黄,不過不是使用 *testing.T 來報告成功或失敗喊衫,而是將輸出打印到 os.Stdout。如果函數(shù)中最后一個注釋以“Output:”開頭杆怕,則輸出將與該注釋進行完全對比(見下例)族购。如果注釋以"Unorder output:" 開頭,則將輸出與注釋進行對比陵珍,但忽略行的順序寝杖。一個沒有上述注釋的 example 測試將被編譯但是不執(zhí)行。如果“Output:”之后沒有任何文本互纯,也會編譯執(zhí)行并預期不會有任何輸出瑟幕。

Godoc顯示ExampleXxx的主體以演示函數(shù),常量或變量Xxx的使用。具有接收器類型T或* T的方法M的示例被命名為ExampleT_M只盹。給定函數(shù)辣往,常量或變量可能有多個示例,由尾隨_xxx區(qū)分殖卑,其中xxx是不以大寫字母開頭的后綴站削。

以下是一個example測試方法示例:

func ExamplePrintln() {
        Println("The output of\nthis example.")
        // Output: The output of
        // this example.
}

以下是另一個忽略輸出順序的示例:

func ExamplePerm() {
        for _, value := range Perm(4) {
                fmt.Println(value)
        }

        // Unordered output: 4
        // 2
        // 1
        // 3
        // 0
}

當一個測試文件包含單個 example 方法孵稽,至少一個其他方法,類型菩鲜,變量或者常亮定義,且沒有test 或 benchmark 方法的時候被認為是單個示例睦袖。

有關(guān)更多信息珊肃,請參閱測試包的文檔伦乔。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市董习,隨后出現(xiàn)的幾起案子烈和,更是在濱河造成了極大的恐慌皿淋,老刑警劉巖窝趣,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哑舒,死亡現(xiàn)場離奇詭異,居然都是意外死亡洗鸵,警方通過查閱死者的電腦和手機膘滨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門火邓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來德撬,“玉大人砰逻,你說我怎么就攤上這事泛鸟∮欢” “怎么了闸翅?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵坚冀,是天一觀的道長。 經(jīng)常有香客問我记某,道長液南,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任统扳,我火速辦了婚禮咒钟,結(jié)果婚禮上若未,老公的妹妹穿的比我還像新娘陨瘩。我一直安慰自己,他們只是感情好帚湘,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布大诸。 她就那樣靜靜地躺著,像睡著了一般焙贷。 火紅的嫁衣襯著肌膚如雪辙芍。 梳的紋絲不亂的頭發(fā)上羹与,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天纵搁,我揣著相機與錄音,去河邊找鬼徘层。 笑死趣效,一個胖子當著我的面吹牛眼耀,可吹牛的內(nèi)容都是我干的哮伟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼池凄,長吁一口氣:“原來是場噩夢啊……” “哼肿仑!你這毒婦竟也來了碎税?” 一聲冷哼從身側(cè)響起雷蹂,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤匪煌,失蹤者是張志新(化名)和其女友劉穎党巾,沒想到半個月后齿拂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肴敛,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡值朋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年昨登,在試婚紗的時候發(fā)現(xiàn)自己被綠了丰辣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片禽捆。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡胚想,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出统屈,到底是詐尸還是另有隱情愁憔,我是刑警寧澤孽拷,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布脓恕,位于F島的核電站,受9級特大地震影響秋茫,放射性物質(zhì)發(fā)生泄漏学辱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一衙傀、第九天 我趴在偏房一處隱蔽的房頂上張望统抬。 院中可真熱鬧危队,春花似錦茫陆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喜最。三九已至瞬内,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間振乏,已是汗流浹背秉扑。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工舟陆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留秦躯,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓倡缠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親琢唾。 傳聞我的和親對象是個殘疾皇子盾饮,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 備注:本猿翻譯水平有限普办,請各位看客見諒 翻譯內(nèi)容: go1.11 版本中 go help modules文檔內(nèi)容 ...
    星云數(shù)聯(lián)閱讀 2,522評論 0 1
  • 傳統(tǒng)Go構(gòu)建以及包依賴管理 Go在構(gòu)建設(shè)計方面深受Google內(nèi)部開發(fā)實踐的影響衔蹲,比如go get的設(shè)計就深受 G...
    一根很帥的藤藤菜閱讀 13,456評論 0 7
  • vendor 在Go1.5 release的版本的發(fā)布vendor目錄被添加到除了GOPATH和GOROOT之外的...
    _羊羽_閱讀 3,956評論 0 2
  • go 1.11 有了對模塊的實驗性支持踪危,大部分的子命令都知道如何處理一個模塊猪落,比如 run build insta...
    yesuu閱讀 35,507評論 7 30
  • 緣分真是個奇妙的東西笨忌,它讓來自不同地方的人相識官疲,它讓性格不同的人聚集在一起亮隙。 感謝潮職讓我遇見你們溢吻,一群有趣的人。...
    一西阿閱讀 804評論 0 0