主頁 > 後端開發 > Go檔案:Command go

Go檔案:Command go

2020-09-15 05:51:53 後端開發

本文更新于2020-04-08,

翻譯自Command go官方檔案(https://golang.org/cmd/go/,國內可使用https://golang.google.cn/cmd/go/),章節段落結構稍作改變,對應的go版本為1.14,

目錄

  • go
  • go bug——啟動bug報告
  • go build——編譯包及其依賴包
  • go clean——洗掉物件檔案和快取檔案
  • go doc——查看包或符號的檔案
  • go env——列印環境變數
  • go fix——使用新的API更新包代碼
  • go fmt——gofmt(重新格式化)包代碼
  • go generate——通過執行源代碼生成Go檔案
  • go get——添加依賴包至當前模塊并安裝之
  • go help——查看幫助資訊
  • go install——編譯并安裝模塊及其依賴
  • go list——列出包和模塊
  • go mod——模塊維護
    • go mod download——下載模塊至本地快取中
    • go mod edit——通過工具或腳本編輯go.mod
    • go mod graph——列印模塊依賴要求圖
    • go mod init——在當前目錄初始化新模塊
    • go mod tidy——添加缺少的模塊并洗掉未使用的模塊
    • go mod vendor——生成依賴的vendor副本
    • go mod verify——驗證依賴有預期的內容
    • go mod why——解釋為什么需要該包或模塊
  • go run——編譯并運行Go程式
  • go test——測驗包
  • go tool——運行指定的go tool
  • go version——列印Go版本
  • go vet——報告包中有可能的錯誤
  • buildmode主題——構建模式
  • c主題——Go和C之間的呼叫
  • cache主題——構建和測驗快取
  • environment主題——環境變數
  • filetype主題——檔案型別
  • go.mod主題——go.mod檔案
  • gopath主題——GOPATH環境變數
    • GOPATH和模塊
    • internal目錄
    • vendor目錄
  • gopath-get主題——遺留的GOPATH的go get
  • goproxy主題——模塊代理協議
  • importpath主題——import路徑語法
    • 相對匯入路徑
    • 遠程匯入路徑
    • 匯入路徑檢查
  • modules主題——模塊,模塊版本,及更多
    • 模塊支持
    • 定義模塊
    • 主模塊和構建串列
    • 維護模塊依賴要求
    • 偽版本
    • 模塊查詢
    • 模塊兼容性和語意版本控制
    • 模塊代碼布局
    • 模塊下載和校驗
    • 模塊和使用vendor
  • module-get主題——模塊感知的go get
  • module-auth主題——使用go.sum的模塊校驗
    • 模塊校驗失敗
  • module-private主題——非公共模塊的模塊配置
  • packages主題——包串列和模式
  • testflag主題——測驗標志
  • testfunc主題——測驗函式

go

go <command> [arguments]

go是管理Go源代碼的工具,

command可為以下命令:

  • bug:啟動bug報告,
  • build:編譯包及其依賴包,
  • clean:洗掉物件檔案和快取檔案,
  • doc:查看包或符號的檔案,
  • env:列印環境變數,
  • fix:使用新的API更新包代碼,
  • fmt:gofmt(重新格式化)包代碼,
  • generate:通過執行源代碼生成Go檔案,
  • get:添加依賴包至當前模塊并安裝之,
  • help:查看幫助資訊,
  • install:編譯并安裝模塊及其依賴,
  • list:列出包和模塊,
  • mod:模塊維護,
  • run:編譯并運行Go程式,
  • test:測驗包,
  • tool:運行指定的go tool,
  • version:列印Go版本,
  • vet:報告包中有可能的錯誤,

go bug——啟動bug報告

go bug

打開默認瀏覽器并啟動新的bug報告,報告包括有用的系統資訊,

go build——編譯包及其依賴包

go build [-o output] [-i] [build flags] [packages]

編譯指定匯入路徑的包,以及其依賴包,但不安裝結果,

如果構建的引數為單個目錄下的.go檔案串列時,會將它們當作指定單個包的源檔案串列,

當編譯包時,忽略以“_test.go”結尾的檔案,

當編譯單個main包時,生成的可執行檔案會被寫入到以第一個源檔案(如:“go build ed.go rx.go”寫入“ed”或“ed.exe”)或源代碼目錄名(如:“go build unix/sam”寫入“sam”或“sam.exe”)命名的輸出檔案中,當寫入Windows下的可執行檔案時會添加“.exe”后綴,

當編譯多個包或單個非main包時,build編譯包但會丟棄目標物件檔案,行為只用于類似檢查包是否可以構建,

標志:

  • -i:同時安裝目標的依賴包,
  • -o output:強制將結果可執行檔案或物件檔案寫入指定名字的輸出檔案或目錄,而不是在本節最后兩個段落所描述的默認行為,如果指定的名字為一個已存在的目錄,則所有結果可執行檔案將寫入到該目錄中,

構建標志(build flags)會被build、clean、get、install、list、run、test命令共享:

  • -a:強制重新構建已經是最新的包,
  • -asmflags '[pattern=]arg list':傳遞給每次go tool asm呼叫的引數,
  • -buildmode mode:使用的構建模式,更多資訊參閱“go help buildmode”,
  • -compiler name:使用的編譯器名,即runtime.Complier(gccgo或gc),
  • -gccgoflags '[pattern=]arg list':傳遞給每次gccgo編譯器/聯結器呼叫的引數,
  • -gcflags '[pattern=]arg list':傳遞給每次go tool complie呼叫的引數,
  • -installsuffix suffix:在包安裝目錄名字中使用的后綴,以便使輸出檔案與默認構建分開,如使用-race標志,安裝后綴會自動設定為race,或如果顯式設定則在其后追加_race,對-msan也同樣,使用需要使用非默認編譯標志的-buildmode選項也又類似效果,
  • -ldflags '[pattern=]arg list':傳遞給每次go tool link呼叫的引數,
  • -linkshared:鏈接到的之前使用-buildmode=shared生成的共享庫,
  • -mod mode:使用的模塊下載模式:readonly、vendor或mod,更多資訊參閱“go help modules”,
  • -modcacherw:令保留在模塊快取中的新創建的目錄可讀寫,而不是令它們只讀,
  • -modfile file:在模塊感知模式下,讀取(并且可能寫入)備用的go.mod檔案而不是在模塊根目錄下的go.mod檔案,名字為“go.mod”的檔案仍然必須存在用來確定模塊根目錄,但其不會被訪問,當-modfile被指定,備用的go.sum檔案也會被使用:其路徑從-modfile標志產生,通過去除“.mod”擴展名并追加“.sum”,
  • -msan:啟用與記憶體清理程式的互操作,只支持linux/amd64、linux/arm64,并且只能使用clang/llvm作為宿主C編譯器,在linux/arm64上,pie構建模式將被使用,
  • -n:列印實際需執行的命令,但不運行,
  • -p n:可以并行運行的程式——如構建命令或測驗二進制檔案——的數量,默認為可用的CPU的數量,
  • -pkgdir dir:從dir而不是通常的位置安裝和加載所有包(pkg),例如,當使用非標準設定構建時,使用-pkgdir來令在特定的目錄生成包,
  • -race:啟用資料競態檢測,只支持linux/amd64、freebsd/amd64、darwin/amd64、windows/amd64、linux/ppc64le、linux/arm64(只對48位VMA),
  • -tags tag,list:構建期間需滿足的構建標記,為逗號分隔的串列,關于構建標記,參閱go/build包檔案中關于構建約束的描述,(早期Go版本使用空白分隔的串列,已經被棄用,但仍然能識別,)
  • -toolexec 'cmd args':用來呼叫如如vet和asm等工具鏈程式的程式,例如,使用go命令運行“cmd args /path/to/asm ”,而不是運行asm,
  • -trimpath:從目標可執行檔案中移除所有檔案系統路徑,作為檔案系統絕對路徑的替代,記錄下的檔案名將以“go”(對標準庫),或“模塊路徑@版本”(當使用模塊),或“import路徑”(當使用GOPATH)開頭,
  • -v:列印編譯的包名,
  • -work:列印臨時作業目錄并在退出時不洗掉之,
  • -x:列印實際需執行的命令,并運行,

-asmflags、-gccgoflags、-gcflags、-ldflags接受一個以空白分隔的引數串列,用以在構建時傳遞給底層工具,要在串列元素中嵌入空白,需使用單引號或雙引號括起,引數串列前面可以是一個包模式和一個等號,它將該引數串列的使用限制為與該模式匹配的包(有關包模式的說明,請參閱“go help packages”),如果沒有模式,引數串列只應用于命令列中命名的包,這些標志可以使用不同的模式重復指定,以便為不同的包指定不同的引數,如果一個包與多個標志中給定的模式匹配,則使用最后一個指定的,例如:“go build -gcflags=-S fmt”只列印fmt包的反匯編,“go build -gcflags=all=-S fmt”則列印fmt包及其所有依賴包的反匯編,

有關指定包的詳細資訊,參閱“go help packages”,有關包和二進制檔案的安裝位置的詳細資訊,參閱“go help gopath”,有關Go和C/C++之間呼叫的詳細資訊,參閱“go help c”,

注意:構建遵守某些約定,例如在“go help gopath”中描述的,然而,并不是所有專案都能遵守這些約定,使用自己的約定來安裝,或使用一個單獨的軟體構建系統,可以選擇使用低級別的呼叫,如“go tool compile”和“go tool link”,來避免構建工具的開銷和設計決策,

參閱:go install,go get,go clean,

go clean——洗掉物件檔案和快取檔案

go clean [clean flags] [build flags] [packages]

從包源代碼目錄中洗掉物件檔案,go命令在臨時目錄中構建大多數物件檔案,因此go clean主要關心通過其他工具或通過手動呼叫go build遺留下來的物件檔案,

如果給出packages引數或者-i或-r標志,clean將從與匯入路徑對應的每個源檔案目錄中洗掉以下檔案:

  • _obj/:舊的物件檔案目錄,來自Makefile,
  • _test/:舊的測驗檔案目錄,來自Makefile,
  • _testmain.go:舊的gotest檔案,來自Makefile,
  • test.out:舊的測驗日志,來自Makefile,
  • build.out:舊的測驗日志,來自Makefile,
  • *.[568ao]:物件檔案,來自Makefile,
  • DIR(.exe):來自go build,
  • DIR.test(.exe):來自go test -c,
  • MAINFILE(.exe):來自go build MAINFILE.go,
  • *.so:來自SWIG,

在上述串列中,DIR表示目錄路徑的最后一個元素,MAINFILE表示目錄中任何在構建包時未包含的go源檔案的基本名,

標志:

  • -cache:洗掉整個go build快取,
  • -i:洗掉相關的已安裝的歸檔檔案或二進制檔案(由“go install”創建),
  • -modcache:洗掉整個模塊下載快取,包括指定版本依賴的已解壓的源代碼,
  • -n:列印實際需執行的命令,但不運行,
  • -r:遞回地應用于所有由匯入路徑指定的依賴包,
  • -testcache:令go build快取中所有測驗結果過期,
  • -x:列印實際需執行的命令,并運行,

關于構建標志的更多資訊,參閱“go help build”,

關于指定包的更多資訊,參閱“go help packages”,

go doc——查看包或符號的檔案

go doc [-u] [-c] [package|[package.]symbol[.methodOrField]]

列印由引數(包、常量、函式、型別、變數、方法、結構體欄位)指定的項相關的檔案注釋,該項后跟該項下的每個第一級項(該項為包即為包級宣告,該項為型別即為其方法,依次類推)的一行概要,

doc命令接受0個、1個或2個引數,

如使用0個引數,即運行:

go doc

會列印當前目錄下包的包檔案,如果包是命令的包(main包),包的匯出符號會從展示輸出中省略,除非指定了-cmd標志,

當使用一個引數運行時,引數會被視為要展示檔案的項的Go語法表示,引數指定的項取決于GOROOT和GOPATH中安裝的內容,以及引數的格式,引數的格式如下所示:

go doc <pkg>
go doc <sym>[.<methodOrField>]
go doc [<pkg>.]<sym>[.<methodOrField>]
go doc [<pkg>.][<sym>.]<methodOrField>

上述串列中引數匹配的第一項是待列印檔案的項,(參見下面的示例,)但是,如果引數是以大寫字母開頭的,則假設其表示當前目錄中的符號或方法,

對于包,掃描順序是從詞匯上按廣度優先確定的,也就是說,呈現的包是匹配搜索的其中一個,并且為最接近搜索根,在其層次結構中搜索到的從詞匯上來說的第一個,GOROOT樹總是在GOPATH之前被完整掃描,

如果沒有包被指定或被匹配,則選擇當前目錄下的包,因此“go doc Foo”顯示當前目錄中符號為Foo的檔案,

包路徑必須是限定路徑或者是路徑的正確后綴,go工具通常的包機制不適用于:類似“.”和“...”的包路徑元素,是不被go doc實作的,

當使用兩個引數運行時,第一個引數必須是完整的包路徑(而不僅僅是后綴),第二個引數是一個符號、符號的方法或符號的結構體欄位,這與godoc接受的語法類似:

go doc <pkg> <sym>[.<methodOrField>]

在所有的形式中,當匹配符號時,引數的小寫字母不區分大小寫,但大寫字母只匹配大寫,這意味著如果不同的符號有不同的大小寫,則包中小寫字母引數可能有多個匹配,如果這種情況發生,將列印所有匹配項的檔案,

示例:

  • go doc:顯示當前包的檔案,
  • go doc Foo:顯示當前包中Foo的檔案,(Foo以大寫字母開頭,因此其不能匹配為一個包路徑,)
  • go doc encoding/json:顯示encoding/json包的檔案,
  • go doc json:encoding/json的簡寫,
  • go doc json.Number(或go doc json.number):顯示json.Number的檔案和方法概要,
  • go doc json.Number.Int64(或go doc json.number.int64):顯示json.Number的Int64方法的檔案,
  • go doc cmd/doc:顯示doc命令的包檔案,
  • go doc -cmd cmd/doc:顯示doc命令的包檔案和匯出符號,
  • go doc template.new:顯示html/template的New函式的檔案,(html/template從詞匯上來說位于text/template之前,)
  • go doc text/template.new(一個引數):顯示text/template的New函式的檔案,
  • go doc text/template new(兩個引數):顯示text/template的New函式的檔案,

至少在當前的包樹結構中,以下呼叫均會列印json.Decoder的Decode方法的檔案:

  • go doc json.Decoder.Decode
  • go doc json.decoder.decode
  • go doc json.decode
  • cd go/src/encoding/json; go doc decode

標志:

  • -all:顯示包的所有檔案,
  • -c:匹配符號時區分大小寫,
  • -cmd:將命令(main包)當作普通包看待,否則當顯示包的頂層檔案時,main包的匯出符號將被隱藏,
  • -short:每個符號一行表示,
  • -src:顯示符號的完整源代碼,這將顯示其宣告和定義的完整Go代碼,如函式定義(包括函式體),型別宣告或閉包參考的常量塊,輸出可能因此包含未匯出的細節,
  • -u:像匯出符號、方法、欄位一樣顯示未匯出的符號、方法、欄位的檔案,

go env——列印環境變數

go env [-json] [-u] [-w] [var ...]

列印Go環境變數資訊,

env默認像shell腳本(在Windows下,像批處理檔案)一樣列印資訊,如果一個或多個變數名作為引數給定,env將為每個指定名字的變數新起一行列印其值,

標志:

  • -json:以JSON格式列印環境變數,而不是像shell腳本一樣,
  • -u:需要一個或多個引數,如果指定名字的環境變數已經使用“go env -w”設定,則取消其默認設定,
  • -w:需要一個或多個格式為NAME=VALUE的引數,使用指定的值修改指定名字的環境變數的默認設定,

關于環境變數的更多資訊,參閱“go help environment”,

go fix——使用新的API更新包代碼

go fix [packages]

在通過匯入路徑指定的包上運行Go fix命令,

關于fix的更多資訊,參閱“go doc cmd/fix”,關于指定包的更多資訊,參閱“go help packages”,

如需使用特定的選項,運行“go tool fix”,

參閱:go fmt,go vet,

go fmt——gofmt(重新格式化)包代碼

go fmt [-n] [-x] [packages]

在匯入路徑指定的包上運行“gofmt -l -w”命令,將列印被修改的檔案名,

關于gofmt的更多資訊,參閱“go doc cmd/gofmt”,關于指定包的更多資訊,參閱“go help packages”,

標志:

  • -mod:標志的值設定要使用那種模塊下載模式:readonly還是vendor,更多資訊參閱“go help modules”,
  • -n:列印實際需執行的命令,但不運行,
  • -x:列印實際需執行的命令,并運行,

如需使用特定的選項,直接運行gofmt,

參閱:go fix,go vet,

go generate——通過執行源代碼生成Go檔案

go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]

通過在現存檔案中描述的指令執行命令,命令可以運行任何行程,但目的是創建或更新Go源檔案,

go generate永遠不會通過go build、go get、go test等自動運行,必須明確地運行,

go generate掃描檔案搜索指令,指令是如下格式的行:

//go:generate command argument...

(注意:開頭沒有空白,“//go”中間也沒有空白)其中command是要運行的生成器,對應于可在本地運行的可執行檔案,其必須在shell PATH中(如gofmt),或為一個完全限定路徑(如/usr/you/bin/mytool),或為一個命令別名,如下所述,

為了向人類和機器工具傳達,代碼是自動生成的,生成的源代碼應有一行匹配如下的正則運算式(以Go語法):

^// Code generated .* DO NOT EDIT\.$

該行可以出現在檔案的任何位置,但通常放在開頭附近,以便更容易發現,

注意go generate不決議檔案,因此在注釋或多行字串中看起來像指令的行將會被視為指令,

指令的引數是空白分隔的記號,記號可為雙引號引起的字串,在生成器運行時每個記號作為獨立的引數傳遞給生成器,

帶引號的字串使用Go語法,并在執行前進行計算;一個帶引號的字串作為生成器的一個單獨的引數,

go generate在運行生成器時會設定幾個環境變數:

  • $GOARCH:執行時的體系結構(arm、amd64等),
  • $GOOS:執行時的作業系統(linux、windows等),
  • $GOFILE:檔案的基本名(base name),
  • $GOLINE:指令在源檔案中的行號,
  • $GOPACKAGE:包含指令的檔案的包名,
  • $DOLLAR:一個美元符號,

除了變數替換和帶引號的字串求值,在命令列上不會執行諸如“globbing”(檔案名通配符匹配)之類的特殊處理,

作為執行命令前的最后一步,對任何以字母數字命名的環境變數(如$GOFILE或$HOME)的任何呼叫,均會在命令列中展開,在所有的作業系統上環境變數名的展開語法都類似$NAME這樣,由于求值的順序,環境變數甚至在帶引號的字串中也會展開,如果名字為NAME的環境變數未設定,$NAME會展開為空字串,

如下形式的指令:

//go:generate -command xxx args...

表示,只對于此源檔案的接續部分,字串xxx代表由引數指定的命令,這可以用來創建別名或處理多個單詞的生成器,例如:

//go:generate -command foo go tool foo

表示,命令“foo”代表生成器“go tool foo”,

generate按照命令列中給定的順序處理包,一次一個,如果命令列列出一個單獨的目錄中的.go檔案,它們會作為一個單獨的包對待,在包中,generate按照包中檔案名的順序處理源檔案,一次一個,在一個源檔案中,generate按照在檔案中出現的順序運行生成器,一次一個,go generate工具還會設定構建標記“generate”,以便檔案可以被go generate審查但會在構建時忽略,

如果任何一個生成器回傳了錯誤退出狀態,“go generate”會跳過該包所有接續的處理,

生成器運行在包的源代碼目錄中,

標志:

  • -run="":如果非空,指定一個正則運算式來選擇執行的指令,該指令的完整原始源文本(忽略結尾處的空白和換行)匹配正則運算式,

也接受標準的構建標志,包括-v、-n和-x,

  • -n:列印實際需執行的命令,但不運行,
  • -v:列印正在處理的包名和檔案名,
  • -x:列印實際需執行的命令,并運行,

關于構建標志的更多資訊,參閱“go help build”,

關于指定包的更多資訊,參閱“go help packages”,

go get——添加依賴包至當前模塊并安裝之

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

get為當前開發的模塊決議并添加依賴,然后構建并安裝依賴,

第一步是決議需要添加哪些依賴,

對于每個命名的包或包模式,get必須決定相關的模塊使用哪個版本,默認情況下,get查找最后的帶標簽(tag)的發布版本(release),如v0.4.5或v1.2.3,如果沒有帶標簽的發布版本,get查找最后的帶標簽的預發布版本(pre-release),如v0.0.1-pre1,如果根本沒有帶標簽的版本,get查找最后的已知提交,如果該模塊不是已被依賴要求使用較后的版本(例如,比最后的發布版本較新的預發布版本),get將使用它查找到的版本,否則,get將使用當前依賴要求的版本,

默認的版本選擇可通過向包名引數添加@version后綴來覆寫,如“go get golang.org/x/[email protected]”所示,版本version也可以是一個前綴:@1表示以v1開頭的最后的可用版本,完整的查詢語法參閱“go help modules”中“模塊查詢”標題下的內容,

對于在源代碼控制倉庫中存盤的模塊,版本version后綴也可以是一次提交哈希、分支識別符號、或其他源代碼控制系統已知的語法,如“'go get golang.org/x/text@master”,注意被其它模塊查詢語法覆寫的分支名不能顯式地選擇,例如,后綴@v2表示以v2開頭的最后的版本,而不是名字為v2的分支,

如果正在決議的模塊已經是當前開發模塊的依賴,get將更新依賴要求的版本,指定一個比當前依賴要求的版本較早的版本是有效的,并且會降級依賴,版本version后綴為@none表示依賴應該被完全洗掉,根據需要降級或洗掉其上的依賴模塊,

版本version后綴@latest顯式要求使用指定路徑命名的模塊的最后的次版本(minor)的發布版本,后綴@upgrade類似@latest,但如果當前已被依賴要求使用比最后的發布版本較新的修訂版本(revision)或預發布版本,將不會降級模塊,后綴@patch要求使用最后的補丁版本(patch):和當前依賴要求的版本有相同主版本(major)和次版本的最后的發布版本,和@upgrade類似,當已依賴要求使用較新的版本時,@patch不會降級模塊,如果指定路徑的模塊還沒有被依賴要求,@upgrade和@patch等同于@latest,

雖然get默認使用包含命名包的模塊的最后版本,但其不會使用該模塊的依賴模塊的最后版本,相反,其偏向于使用該模塊要求的特定依賴版本,例如,最后版本的模塊A依賴要求使用模塊B的v1.2.3,同時模塊B的v1.2.4和v1.3.1也可用,那么“go get A”將使用模塊A的最后版本但使用模塊B的v1.2.3,就如模塊A要求的那樣,(如果對特定模塊有依賴要求沖突,那么“go get”將通過使用最大化依賴版本來解決依賴要求沖突,)

通常,添加一個新依賴可能需要升級現有的依賴以保證正常構建,并且“go get”會自動完成,同樣,降級一個依賴可能需要降級其他的依賴,并且“go get”也會自動完成,

第二步是下載(如果需要)、構建、安裝指定名字的包,

如果引數命名一個模塊但不命名一個包(因為在模塊的根目錄中沒有Go源代碼),那么該引數將跳過安裝步驟,而不會導致構建失敗,例如“go get golang.org/x/perf”仍然會成功,即使該匯入路徑沒有相關的代碼,

注意,包模式是允許的,且會在決議模塊版本后進行擴展,例如,“go get golang.org/x/perf/cmd/...”添加最后的golang.org/x/perf并然后安裝最后版本中的命令(cmd目錄下),

如果沒有指定包名引數,“go get”應用于當前目錄下的Go包,如果有的話,特別地,“go get -u”和“go get -u=patch”更新該包的所有依賴,如無包名引數也沒有-u標志,“go get”等同于“go install”,“go get -d”等同于“go list”,

標志:

  • -d:下載構建指定名字的包所需的源代碼,包括下載所需的依賴的源代碼,但不構建和安裝它們,
  • -insecure:允許使用如HTTP等不安全的方案,從倉庫拉取以及決議自定義域名,謹慎使用,
  • -t:同時添加命令列中指定的包構建測驗所需的模塊,
  • -u:同時更新命令列中指定的包的依賴模塊,令依賴模塊使用較新的次版本的發布版本或補丁版本的發布版本,前提是這些版本可用,繼續前面的例子,“go get -u A”會使用模塊A的最后版本和模塊B的v1.3.1(而不是v1.2.3),如果模塊B依賴要求模塊C,但模塊C不是構建模塊A的依賴(不包括測驗),那么模塊C將不會被更新,
  • -u=patch:(不同于-u)同樣更新依賴模塊,但不同之處在于默認選擇補丁版本的發布版本,繼續前面的例子,“go get -u=patch A@latest”將使用模塊A的最后版本和模塊B的v1.2.4(而不是v1.2.3),而“go get -u=patch A”將使用模塊A的補丁版本的發布版本,

當-t和-u一起使用時,將也會更新構建測驗所需的模塊的依賴模塊,

關于模塊的更多資訊,參閱“go help modules”,

關于指定包的更多資訊,參閱“go help packages”,

上文介紹了使用模塊來管理源代碼和依賴的行為,如果相反,go命令運行在GOPATH模式下,“go help get”的內容會不同,類似地,get的標志和行為的細節也會改變,參閱“go help modules”和“go help gopath-get”,

參閱:go build、go install、go clean、go mod,

go help——查看幫助資訊

go help <command>
go help <topic>

使用“go help <command>”獲取關于命令(command,即 go 小節中的命令)的更多資訊,使用“go help <topic>”獲取關于主題(topic)的更多資訊,

額外的幫助主題為:

  • buildmode:構建模式,
  • c:Go和C之間的呼叫,
  • cache:構建和測驗快取,
  • environment:環境變數,
  • filetype:檔案型別,
  • go.mod:go.mod檔案,
  • gopath:GOPATH環境變數,
  • gopath-get:遺留的GOPATH的go get,
  • goproxy:模塊代理協議,
  • importpath:import路徑語法,
  • modules:模塊,模塊版本,及更多,
  • module-get:模塊感知的go get,
  • module-auth:使用go.sum的模塊校驗,
  • module-private:非公共模塊的模塊配置,
  • packages:包串列和模式,
  • testflag:測驗標志,
  • testfunc:測驗函式,

go install——編譯并安裝模塊及其依賴

go install [-i] [build flags] [packages]

編譯并安裝匯入路徑指定的包,

可執行檔案安裝在GOBIN環境變數指定的目錄中,默認為$GOPATH/bin或如果GOPATH環境變數沒有設定時為$HOME/go/bin,$GOROOT中的可執行檔案安裝在$GOROOT/bin或$GOTOOLDIR,而不是$GOBIN,

當模塊感知模式禁用,非可執行檔案的其他包將安裝在目錄$GOPATH/pkg/$GOOS_$GOARCH中,當模塊感知模式啟用,非可執行檔案的其他包將會被構建和快取,但不會被安裝,

標志:

  • -i:同時安裝指定名字的包的依賴,

關于構建標志的更多資訊,參閱“go help build”,關于指定包的更多資訊,參閱“go help packages”,

參閱:go build、go get、go clean,

go list——列出包和模塊

go list [-f format] [-json] [-m] [list flags] [build flags] [packages]

列出指定名字的包,一行一個,最常用的標志是-f和-json,用以控制每個包的輸出列印格式,其他標志,檔案于下文,控制更多特定的細節,

默認輸出顯示包的匯入路徑:

bytes
encoding/json
github.com/gorilla/mux
golang.org/x/net/html

標志(其他標志的說明需參閱-f或-m):

  • -complied:將CompiledGoFiles設定為提交給編譯器的Go源檔案,通常,這意味著其會重復GoFiles列出的檔案,然后也會添加通過處理CgoFiles和SwigFiles生成的Go代碼,Imports串列包含來自GoFiles和CompiledGoFiles所有匯入的并集,

  • -deps:不只是遍歷指定名字的包,也會遍歷它們的依賴,list以深度優先后序遍歷的方式遍歷它們,因此一個包會在它的所有依賴之后列出,未在命令列中顯式列出的包將有一個設定為true的DepOnly欄位,

  • -e:改變對錯誤包的處理方式,那些錯誤包或者不存在或者內容殘缺,默認情況下,list命令為每個錯誤包列印一條錯誤資訊至標準錯誤輸出中,然后在普通的列印中忽略這些錯誤包,使用-e標志,list命令將不會列印錯誤資訊至標準錯誤輸出中,而是以普通列印的方式處理錯誤包,錯誤包將有非空的ImportPath和非nil的Error欄位;其他資訊可能會也可能不會缺失(置為零值),

  • -export:將Export欄位設定為包含指定包最新匯出資訊的檔案名,

  • -f:指定list使用的替換格式,使用template包的語法,默認的輸出等同于-f '{{.ImportPath}}',傳遞給模板的結構體為:

    type Package struct {
    	Dir           string   // 包含包源代碼的目錄
    	ImportPath    string   // 目錄中包的匯入路徑
    	ImportComment string   // 包說明中匯入注釋的路徑
    	Name          string   // 包名
    	Doc           string   // 包檔案字串
    	Target        string   // 安裝路徑
    	Shlib         string   // 包含本包的共享庫(只在設定-linkshared時使用)
    	Goroot        bool     // 本包是否在GOROOT中
    	Standard      bool     // 本包是否是Go標準庫之一
    	Stale         bool     // “go install”會否為本包進行一些處理
    	StaleReason   string   // 當Stale==true時的決議原因
    	Root          string   // 包含本包的GOROOT或GOPATH目錄
    	ConflictDir   string   // 本目錄在$GOPATH中的同名目錄
    	BinaryOnly    bool     // 是否僅為二進制包(不再支持)
    	ForTest       string   // 包只在該指定名字包的測驗下使用
    	Export        string   // 包含匯出資料的檔案(當使用-export時)
    	Module        *Module  // 包包含的模塊的資訊,如果有的話(可以為nil)
    	Match         []string // 匹配本包的命令列模式
    	DepOnly       bool     // 如為true,則包只是一個依賴,未在命令列中顯式列出
    	
    	// 源檔案
    	GoFiles         []string // .go源檔案(不包括CgoFiles、TestGoFiles、XTestGoFiles中的檔案)
    	CgoFiles        []string // import "C"的.go源檔案
    	CompiledGoFiles []string // 提交給編譯器的.go檔案(當使用-compiled時)
    	IgnoredGoFiles  []string // 由于構建限制被忽略的.go源檔案
    	CFiles          []string // .c源檔案
    	CXXFiles        []string // .cc/.cxx/.cpp源檔案
    	MFiles          []string // .m源檔案
    	HFiles          []string // .h/.hh/.hpp/.hxx源檔案
    	FFiles          []string // .f/.F/.for/.f90的Fortran源檔案
    	SFiles          []string // .s源檔案
    	SwigFiles       []string // .swig檔案
    	SwigCXXFiles    []string // .swigcxx檔案
    	SysoFiles       []string // 添加到歸檔的.syso物件檔案
    	TestGoFiles     []string // 包中的_test.go檔案
    	XTestGoFiles    []string // 包外的_test.go檔案
    	
    	// Cgo指令
    	CgoCFLAGS    []string // cgo:給C編譯器的標志
    	CgoCPPFLAGS  []string // cgo:給C預編譯器的標志
    	CgoCXXFLAGS  []string // cgo:給C++編譯器的標志
    	CgoFFLAGS    []string // cgo:給Fortran編譯器的標志
    	CgoLDFLAGS   []string // cgo:給聯結器的標志
    	CgoPkgConfig []string // cgo:pkg-config名字
    	
    	// 依賴資訊
    	Imports      []string          // 本包使用的匯入路徑
    	ImportMap    map[string]string // 原始匯入路徑到ImportPath的映射(標識入口資訊被省略)
    	Deps         []string          // 所有(遞回的)匯入依賴
    	TestImports  []string          // TestGoFiles使用的匯入依賴
    	XTestImports []string          // XTestGoFiles使用的匯入依賴
    	
    	// 錯誤資訊
    	Incomplete bool            // 本包或依賴包是否有錯誤
    	Error      *PackageError   // 加載本包的錯誤
    	DepsErrors []*PackageError // 加載依賴包的錯誤
    }
    

    vendor目錄中的包報告的ImportPath包括vendor目錄自身的路徑(例如,“d/vendor/p”而不是“p”),以便ImportPath唯一地標識一個給定包的副本,Imports、Deps、TestImports、和XTestImports串列同樣包含這種擴展的匯入路徑,更多關于使用vendor的資訊參閱golang.org/s/go15vendor,

    錯誤資訊,如果有的話,為:

    type PackageError struct {
    	ImportStack   []string // 從命令列指定的包名到此的最短路徑
    	Pos           string   // 錯誤的位置(如果有的話為,檔案名:行號:列號)
    	Err           string   // 錯誤自身
    }
    

    模塊資訊為一個Module結構體,其定義在下文的-m討論中,

    模板函式“join”呼叫strings.Join,

    模板函式“context”回傳構建的背景關系,定義如下:

    type Context struct {
    	GOARCH        string   // 目標體系結構
    	GOOS          string   // 目標作業系統
    	GOROOT        string   // GOROOT
    	GOPATH        string   // GOPATH
    	CgoEnabled    bool     // cgo是否可用
    	UseAllFiles   bool     // 是否使用所有檔案,從而忽略使用+build指定行和檔案名
    	Compiler      string   // 在計算目標路徑時假定的編譯器
    	BuildTags     []string // 構建約束,用以匹配+build指定的行
    	ReleaseTags   []string // 與當前發布版本兼容的發布版本
    	InstallSuffix string   // 安裝目錄名字中使用的后綴
    }
    

    關于這些欄位含義的更多資訊,參閱go/build包的Context型別的檔案,

    Dir、Target、Shlib、Root、ConflictDir和Export中的檔案路徑均為絕對路徑,

    默認情況下,GoFiles、CgoFiles等串列中的名字為Dir目錄中的檔案(亦即,相對于Dir的路徑,而不是絕對路徑),當使用-complied和-test標志時添加的生成檔案為指向生成的Go源代碼的快取拷貝的絕對路徑,即使它們為Go源檔案,路徑可能不是以“.go”結尾,

  • -find:找出指定名字的包但不決議它們的依賴:Imports和Deps串列將會為空,

  • -json:包資料以JSON格式列印,而不是使用template包的格式,

  • -m:列出模塊而不是包,

    當列出模塊時,-f標志仍然指定一個應用于Go結構體的格式模板,但現在為一個Module結構體:

    type Module struct {
    	Path      string       // 模塊路徑
    	Version   string       // 模塊版本
    	Versions  []string     // 可獲得的模塊版本(當使用-versions時)
    	Replace   *Module      // 被此模塊替代
    	Time      *time.Time   // 版本創建的時間
    	Update    *Module      // 可獲得的更新,如果有的話(當使用-u時)
    	Main      bool         // 是否為主模塊?
    	Indirect  bool         // 該模塊是否只為主模塊的間接依賴?
    	Dir       string       // 該模塊保存檔案的目錄,如果有的話
    	GoMod     string       // 該模塊go.mod檔案的路徑,如果有的話
    	GoVersion string       // 模塊中使用的go版本
    	Error     *ModuleError // 加載模塊時的錯誤
    }
    
    type ModuleError struct {
    	Err string // 錯誤自身
    }
    

    如果模塊在模塊快取中或如果-modfile標志被使用,GoMod指向的檔案可能在模塊目錄之外,

    默認的輸出是列印模塊路徑,然后是關于版本和替代的資訊,如果有的話,例如,“go list -m all”可能列印:

    my/main/module
    golang.org/x/text v0.3.0 => /tmp/text
    rsc.io/pdf v0.1.1
    

    Module結構體有一個String方法,用以格式化輸出的這一行,因此默認格式等同于-f '{{.String}}',

    注意,當模塊被替代,其Replace欄位描述替代的模塊,其Dir欄位設定為替代模塊的源代碼的目錄,如果有的話,(也就是說,如果Replace不為nil,那么Dir設定為Replace.Dir,無法訪問被替代的源代碼,)

    list -m的引數會被決議為模塊的串列,而不是包的串列,主模塊是包含當前目錄的模塊,活躍的(active)模塊為主模塊及其依賴,不帶引數,list -m顯示主模塊,帶引數,list -m顯示引數指定的模塊,任何活躍的模塊都可以通過其模塊路徑指定,特殊的模式“all”指定所有活躍的模塊,首先是主模塊,然后是使用模塊路徑排序的依賴,包含“...”的模式指定其模塊路徑匹配該模式的活躍模塊,path@version形式的查詢指定該查詢的結果,不限于活躍的模塊,關于模塊查詢的更多資訊,參閱“go help modules”,

    模板函式“module”使用單個字串引數,必須為模塊路徑或查詢,并以Module結構體的形式回傳指定的模塊,如果發生錯誤,結果將是帶有非nil的Error欄位的Module結構體,

  • -text:不只是報告指定名字的包,也報告它們的測驗二進制檔案(對帶有測驗的包),從而將測驗二進制檔案是怎樣構建的準確地傳遞給源代碼分析工具,測驗二進制檔案的報告的匯入路徑為包的匯入路徑添加“.text”后綴,如“math/rand.test”,當構建測驗時,有時候需要重新構建測驗特定的某些依賴(最常見的是被測驗的包本身),為特定的測驗二進制檔案重新編譯的包的報告的匯入路徑,會添加一個空格和以括號括起的測驗二進制檔案的名字,如“math/rand [math/rand.test]”或“regexp [sort.test]”,ForTest也會設定為正在被測驗的包名(在此前的例子中為“math/rand”或“sort”),

  • -u:添加關于可用升級的資訊,當給定模塊的最后版本比當前模塊較新時,-u設定Module的Update欄位為關于較新模塊的資訊,Module的String方法通過在當前版本后面格式化以括號括起的較新版本來表示一個可獲得的升級,例如,“go list -m -u all”可能列印:

    my/main/module
    golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
    rsc.io/pdf v0.1.1 [v0.1.2]
    

    (對工具來說,“go list -m -u -json all”可能更便于決議,)

  • -versions:設定Module的Versions欄位為該模塊的所有已知版本的串列,根據語意版本進行排序,從最早至最后,該標志也會改變默認的輸出格式來顯示模塊路徑,其后接著以空格分隔的版本串列,

關于構建標志的更多資訊,參閱“go help build”,

關于指定包的更多資訊,參閱“go help packages”,

關于模塊的更多資訊,參閱“go help modules”,

go mod——模塊維護

go mod <command> [arguments]

command可為以下命令:

  • download:下載模塊至本地快取中,
  • edit:通過工具或腳本編輯go.mod,
  • graph:列印模塊依賴要求圖,
  • init:在當前目錄初始化新模塊,
  • tidy:添加缺少的模塊并洗掉未使用的模塊,
  • vendor:生成依賴的vendor副本,
  • verify:驗證依賴有預期的內容,
  • why:解釋為什么需要該包或模塊,

go mod提供對模塊操作的訪問,

注意對模塊的支持內置于所有go命令,不只是“go mod”,例如,依賴的日常添加、洗掉、升級、降級應該使用“go get”來完成,關于模塊功能的概述,參閱“go help modules”,

關于命令的更多資訊,參閱“go help mod ”,

go mod download——下載模塊至本地快取中

go mod download [-x] [-json] [modules]

download下載指定名字的模塊,可為選擇主模塊依賴的模塊模式,或path@version形式的模塊查詢,不帶引數,download應用于主模塊的所有依賴,

go命令將在常規執行期間根據需要自動下載模塊,“go mod download”命令主要用于預填充本地快取或計算Go模塊代理的結果,

默認情況下,download不向標準輸出寫入內容,其可能列印進度資訊和錯誤至標準錯誤輸出,

標志:

  • -json:列印一系列JSON物件至標準輸出,描述每個下載的模塊(或失敗),相當于該Go結構體:

    type Module struct {
    	Path     string // 模塊路徑
    	Version  string // 模塊版本
    	Error    string // 加載模塊時的錯誤
    	Info     string // 快取的.info檔案絕對路徑
    	GoMod    string // 快取的.mod檔案絕對路徑
    	Zip      string // 快取的.zip檔案絕對路徑
    	Dir      string // 快取的源檔案根目錄絕對路徑
    	Sum      string // 路徑、版本的校驗和(如go.sum中所示)
    	GoModSum string // go.mod的校驗和(如go.sum中所示)
    }
    
  • -x:列印實際需執行的命令,并運行,

關于模塊查詢的更多資訊,參閱“go help modules”,

go mod edit——通過工具或腳本編輯go.mod

go mod edit [editing flags] [go.mod]

edit提供一個編輯go.mod的命令列介面,主要提供給工具或腳本使用,它只讀取go.mod;不查找涉及模塊的資訊,默認情況下,edit讀寫主模塊的go.mod檔案,但也可以在標志后指定不同的目標檔案,

標志:

  • -dropexclude=path@version:洗掉給定模塊路徑和版本的排除項,

  • -dropreplace=old[@v]:洗掉給定模塊路徑和版本的替代,如果@v省略,洗掉該模塊不帶版本的替代,

  • -droprequire=path:洗掉給定的模塊路徑依賴要求的模塊,該標志主要提供給工具用以理解模塊圖,用戶應該使用“go get path@none”,可令其它go.mod根據需要調整來滿足其它模塊施加的限制,

  • -exclude=path@version:添加給定模塊路徑和版本的排除項,注意如果排除項已經存在-exclude=path@version是無操作的,

  • -fmt:重新格式化go.mod檔案,不作其他改變,使用或重寫go.mod檔案的任何其他修改也意味著這種重新格式化,需要該標志的唯一情形是沒有指定其它標志,如“go mod edit -fmt”,

  • -go=version:設定期望的Go語言版本,

  • -json:以JSON格式列印最終的go.mod,而不是將其寫回go.mod,JSON輸出對應于這些Go型別:

    type Module struct {
    	Path string
    	Version string
    }
    
    type GoMod struct {
    	Module  Module
    	Go      string
    	Require []Require
    	Exclude []Module
    	Replace []Replace
    }
    
    type Require struct {
    	Path string
    	Version string
    	Indirect bool
    }
    
    type Replace struct {
    	Old Module
    	New Module
    }
    
  • -module:修改模塊路徑(go.mod檔案的模塊行),

  • -print:以其文本格式列印最終的go.mod,而不是將其寫回go.mod,

  • -replace=old[@v]=new[@v]:添加給定模塊路徑和版本對的替代,如果old@v中的@v省略,則添加左側模塊不帶版本的替代,適用于左側模塊路徑的所有版本,如果new@v中的@v省略,新路徑應為本地模塊根目錄,而不是模塊路徑,注意-replace覆寫old[@v]任何冗余的替代,因此省略@v將洗掉對特定版本的現有替代,

  • -require=path@version:添加給定的模塊路徑和版本依賴要求的模塊,注意-require覆寫該路徑任何已存在的依賴要求的模塊,該標志主要提供給工具用以理解模塊圖,用戶應該使用“go get path@version”,可令其它go.mod根據需要調整來滿足其它模塊施加的限制,

-require、-droprequire、-exclude、-dropexclude、-replace、-dropreplace標志可以重復,根據給定的順序應用修改,

注意這只描述go.mod檔案自身,不描述其他間接參考的模塊,對于構建可使用的的模塊的完整集合,使用“go list -m -json all”,

例如,工具可以通過決議“go mod edit -json”的輸出以資料結構體的方式獲取go.mod,然后可通過使用-require、-exclude等呼叫“go mod edit”來作出修改,等等,

go mod graph——列印模塊依賴要求圖

go mod graph

以文本形式列印模塊依賴要求圖(已應用替代),輸出的每行有兩個空格分隔的欄位:模塊和其依賴要求中的一個,每個模塊都被標記為path@version形式的字串,除了主模塊,其沒有@version后綴,

go mod init——在當前目錄初始化新模塊

go mod init [module]

初始化并寫入一個新的go.mod至當前目錄中,實際上是創建一個以當前目錄為根的新模塊,檔案go.mod必須不存在,如果可能,init會從import注釋(參閱“go help importpath”)或從版本控制配置猜測模塊路徑,要覆寫此猜測,提供模塊路徑作為引數,

go mod tidy——添加缺少的模塊并洗掉未使用的模塊

go mod tidy [-v]

確保go.mod與模塊中的源代碼一致,它添加構建當前模塊的包和依賴所必須的任何缺少的模塊,洗掉不提供任何有價值的包的未使用的模塊,它也會添加任何缺少的條目至go.mod并洗掉任何不需要的條目,

標志:

  • -v:列印被洗掉的模塊的資訊至標準錯誤輸出,

go mod vendor——生成依賴的vendor副本

go mod vendor [-v]

重置主模塊的vendor目錄,使其包含構建和測驗所有主模塊的包所需要的所有包,不包括vendor中的包的測驗代碼,

  • -v:列印vendor的模塊和包的名字至標準錯誤輸出,

go mod verify——驗證依賴有預期的內容

go mod verify

檢查存盤在本地下載源代碼快取中的當前模塊的依賴,是否自從下載之后未被修改,如果所有模塊都未被修改,列印“all modules verified”,否則報告哪個模塊已經被修改并令“go mod”以非0狀態退出,

go mod why——解釋為什么需要該包或模塊

go mod why [-m] [-vendor] packages...

標志:

  • -m:默認情況下,why在匯入圖中展示從主模塊到每個列出的包的最短路徑,如果給出-m標志,why將引數視為一個模塊的串列并找出每個模塊中的所有包的路徑,
  • -vendor:默認情況下,why查詢與“go list all”匹配的包圖,包括對可達包的測驗相關的包,-vendor標志令why將依賴包的測驗相關的包排除在外,

輸出是一系列的小節,和命令列中每個包或模塊的名字一一對應,以空行分隔,每個小節以注釋行“# package”或“# module”開頭,給出目標包或模塊,隨后的行通過匯入圖給出路徑,一個包一行,如果包或模塊沒有被主模塊參考,該小節將顯示單獨一個帶圓括號的提示資訊來表明該事實,

例如:

$ go mod why golang.org/x/text/language golang.org/x/text/encoding
# golang.org/x/text/language
rsc.io/quote
rsc.io/sampler
golang.org/x/text/language

# golang.org/x/text/encoding
(main module does not need package golang.org/x/text/encoding)
$

go run——編譯并運行Go程式

go run [build flags] [-exec xprog] package [arguments...]

編譯并運行指定名字的main Go包,通常包是作為一個單獨的目錄中的.go源檔案串列指定的,但也可以是匯入路徑、檔案系統路徑、或匹配單獨的已知包的模式,例如“go run .”或“go run my/cmd”,

標志:

  • -exec:默認情況下,“go run”直接運行編譯的二進制檔案:“a.out arguments...”,如果給定-exec標志,“go run”使用xprog呼叫二進制檔案:“xprog a.out arguments...”,

    如果-exec標志未給定,GOOS或GOARCH與系統默認值不同,一個名字為go_$GOOS_$GOARCH_exec的程式可在當前查找目錄下找到,“go run”使用該程式呼叫二進制檔案,如“go_nacl_386_exec a.out arguments...”,當模擬器或其他執行方法可用時,這允許交叉編譯的程式執行,

run的退出狀態不是編譯的二進制檔案的退出狀態,

關于構建標志的更多資訊,參閱“go help build”,關于指定包的更多資訊,參閱“go help packages”,

參閱:go build,

go test——測驗包

go test [build/test flags] [packages] [build/test flags & test binary flags]

“go test”自動測驗以匯入路徑命名的包,它以如下格式列印測驗結果概要:

ok   archive/tar   0.011s
FAIL archive/zip   0.022s
ok   compress/gzip 0.033s
...

每個失敗的包后跟隨詳細的輸出,

“go test”將與名字匹配檔案模式“*test.go”的任何檔案一起,重新編譯每個包,這些附加的檔案可以包含test函式、benchmark函式、example函式,更多資訊參閱“go help testfunc”,每個列出的包都會令到執行單獨的測驗二進制檔案,以“”(包括“_test.go”)或“.”開頭的檔案會被忽略,

宣告帶后綴“_test”的包的測驗檔案將被編譯為單獨的包,然后與main包的測驗二進制檔案鏈接并運行,

go tool將忽略名字為“testdata”的目錄,令其可以持有被測驗所需的輔助資料,

作為構建測驗二進制檔案的一部分,go test在包及其測驗源檔案上運行go vet來發現顯而易見的問題,如果go vet發現任何問題,go test報告它們且不運行測驗二進制檔案,只使用默認go vet檢查的高可信的子集,該自己是:“atomic”、“bool”、“buildtags”、“nilfunc”和“printf”,你可以通過“go doc cmd/vet”查看這些及其它vet測驗的檔案,要禁止運行go vet,使用-vet=off標志(參閱 testflag主題——測驗標志 小節),

所有的測驗輸出和概要行都列印至go命令的標準輸出,即使test列印它們至它自己的標準錯誤輸出,(go命令的標準錯誤輸出被保留為列印構建測驗的錯誤,)

go test以兩種不同的模式運行:

第一種,稱為本地目錄模式,發生在當go test不使用有包引數呼叫時(例如,“go test”或“go test -v”),在這種模式下,go test編譯在當前目錄下找到的包源檔案和測驗檔案,然后運行生成的測驗二進制檔案,在這種模式下,快取(在下面討論)被禁用,包測驗完成后,go test列印一行概要行展示測驗狀態(“ok”或“FAIL”)、包名和消耗的時間,

第二種,稱為包串列模式,發生在當go test使用顯式的包引數呼叫時(例如“go test math”、“go test ./...”甚至“go test .”),在這種模式下,go test編譯并測驗每個在命令列列出的包,如果一個包測驗通過,go test只列印最終的“ok”概要行,如果一個包測驗失敗,go test列印完整的測驗輸出,如果使用-bench或-v標志呼叫(參閱 testflag主題——測驗標志 小節),即使通過了包測驗,go test也列印完整的輸出,以便展示要求的基準測驗結果或詳細日志,對所有列出的包的包測驗完成后,且它們的輸出被列印,如果任一個包測驗失敗,go test列印最終的“FAIL”狀態,

只在包串列模式,go test快取成功的包測驗結果來避免不必要的測驗重復運行,當測驗的結果可以從快取恢復時,go test將重新展示之前的輸出而不是再次運行測驗二進制檔案,當這種情況發生時,go test在概要行中列印“(cached)”取代消耗的時間,

快取匹配的規則為,運行只涉及相同的測驗二進制檔案,且命令列中的標志完全來自一個受限的“可快取”測驗標志集合,定義為-cpu、-list、-parallel、-run、-short和-v,如果go test的運行有任何不在這個集合中的測驗或非測驗標志,結果是不被快取的,要禁用測驗快取,使用可快取標志以外的測驗標志或引數,顯式禁用測驗快取的慣用方式為使用-count=1,在包源代碼根目錄(通常為$GOPATH)內打開檔案或查詢環境變數的測驗只匹配將來的檔案和環境變數未改變的測驗運行,快取的測驗結果被視為立即執行的,因此一個成功的包測驗結果將被快取且重用時忽略-timeout設定,

除了構建標志,“go test”自身處理的標志還有:

  • -args:傳遞命令列中余下的引數(所有在-args后面的引數)至測驗二進制檔案,不決議且不修改,因為該標志使用命令列中余下的引數,包串列(如果有)必須出現在該標志之前,
  • -c:編譯測驗二進制檔案為pkg.test但不運行之(pkg是包的匯入路徑的最后的元素),檔案名可以被-o標識修改,
  • -exec xprog:使用xprog運行測驗二進制檔案,其行為與“go run”相同,詳細資訊參閱“go help run”,
  • -i:安裝測驗的依賴包,不運行測驗,
  • -json:轉換測驗輸出為適合自動化執行的JSON格式,關于編碼的詳細資訊參閱“go doc test2json”,
  • -o file:編譯測驗二進制檔案至指定名字的檔案,測驗仍會運行(除非指定-c或-i),

測驗二進制檔案也接受控制測驗執行的標志;這些引數也可被“go test”使用,詳細資訊參閱“go help testflag”,

關于構建標志的更多資訊,參閱“go help build”,關于指定包的更多資訊,參閱“go help packages”,

參閱:go build、go vet,

go tool——運行指定的go tool

go tool [-n] command [args...]

運行引數指定的go tool命令,不帶引數則列印已知的工具串列,

標志:

  • -n:列印將會執行的命令但不執行之,

關于每個tool命令的更多資訊,參閱“go doc cmd/”,

go version——列印Go版本

go version [-m] [-v] [file ...]

列印Go可執行檔案的構建資訊,

go version報告用來構建每個指定名字的可執行檔案的Go版本,

如果命令列中沒有指定檔案,go version列印其自身的版本資訊,

標志:

  • -m:當可以獲得的時候,令go version列印每個可執行檔案的內嵌的模塊版本資訊,在輸出中,模塊資訊包含跟在版本行之后的多行,每行由前導制表符縮進,
  • -v:如果指定一個目錄,go version遞回地遍歷該目錄,查找可以識別的Go二進制檔案并報告它們的版本,默認情況下,go version不報告在目錄掃描期間發現的無法識別的檔案,-v標志令其報告無法識別的檔案,

參閱:go doc runtime/debug.BuildInfo,

go vet——報告包中有可能的錯誤

go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]

在通過匯入路徑指定名字的包上運行go vet命令,

關于vet和其標志的更多資訊,參閱“go doc cmd/vet”,關于指定包的更多資訊,參閱“go help packages”,關于檢查程式及其標志的串列,參閱“go tool vet help”,關于諸如“printf”的特定檢查程式的詳細資訊,參閱“go tool vet help printf”,

標志:

  • -n:列印將會執行的命令但不執行之,

  • -vettool=prog:選擇帶有備選或附加檢查的不同的分析工具,例如,可以使用這些命令來構建和運行“shadow”分析器:

    go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
    go vet -vettool=$(which shadow)
    
  • -x:列印將會執行的命令并執行之,

go vet支持的構建標志是那些控制包決議和執行的標志,如-n、-x、-v、-tags和-toolexec,關于這些標志的更多資訊,參閱“go help build”,

參閱:go fmg、go fix,

buildmode主題——構建模式

“go build”和“go install”命令使用-buildmode引數,用來表示要構建哪一種物件檔案,當前支持的值為:

(譯注:下述構建模式如無特別說明,均可列出多個包同時構建,)

  • -buildmode=archive:構建列出的非main包生成.a檔案,main包被忽略,
  • -buildmode=c-archive:構建列出的main包,加上其匯入的所有包,生成C歸檔檔案,可呼叫的符號只為那些使用cgo的// export comment匯出的函式,要求只能列出一個main包,
  • -buildmode=c-shared:構建列出的main包,加上其匯入的所有包,生成C共享庫,可呼叫的符號只為那些使用cgo的// export comment匯出的函式,要求只能列出一個main包,
  • -buildmode=default:構建列出的main包生成可執行檔案,構建列出的非main包生成.a檔案(默認行為),
  • -buildmode=exe:構建列出的main包及其匯入的所有包生成可執行檔案,非main包被忽略,
  • -buildmode=pie:構建列出的main包及其匯入的所有包生成地址無關可執行檔案(position independent executables,即PIE),非main包被忽略,
  • -buildmode=plugin:構建列出的main包,加上其匯入的所有包,生成Go插件(plugin),非main包被忽略,
  • -buildmode=shared:合并所有列出的非main包生成單獨的共享庫,共享庫可在當使用-linkshared選項構建時使用,main包被忽略,

在AIX上,當鏈接使用以-buildmode=c-archive構建的Go歸檔檔案的C程式時,必須傳遞-Wl,-bnoobjreorder至C編譯器,

c主題——Go和C之間的呼叫

有兩種不同的方式在Go和C/C++代碼之間呼叫,

第一種方式是cgo工具,它是Go發行版的一部分,關于如何使用它的資訊參閱cgo檔案(go doc cmd/cgo),

第二種是SWIG程式,它是語言之間通過介面連接的通用工具,關于SWIG的資訊參閱http://swig.org/,當運行go build時,任何帶有.swig擴展名的檔案將傳遞給SWIG,任何帶.swigcxx擴展名的檔案將使用-c++選項傳遞給SWIG,

當cgo或SWIG任一種被使用時,go build將傳遞所有.c、.m、.s或.S檔案至C編譯器,以及所有.cc、.cpp、.cxx檔案至C++編譯器,可以設定CC或CXX環境變數來依次決定要使用的C或C++編譯器,

cache主題——構建和測驗快取

go命令快取構建輸出以在將來的構建中重用,快取資料的默認位置為當前作業系統標準用戶快取目錄下名字為go-build的子目錄,設定GOCACHE環境變數覆寫該默認值,運行“go env GOCACHE”列印當前快取目錄,

go命令定期地洗掉最近未使用的快取資料,運行“go clean -cache”洗掉所有快取資料,

構建快取會正確地考慮Go源檔案、編譯器、編譯器選項等等的改變:在平常的使用中顯式地清理快取不是必須的,但是,構建快取不檢測由cgo匯入的C庫的改變,如果你在你的系統上對C庫進行了修改,你將需要顯式地清理快取或使用-a構建標志(參閱“go help build”)來強制重新構建那些依賴已經更新了的C庫的包,

go命令也快取成功的包測驗結果,更多細節參閱“go help test”,運行“go clean -testcache”洗掉所有快取的測驗結果(不包括快取的構建結果),

GODEBUG環境變數可以啟用列印關于快取狀態的調試資訊:

  • GODEBUG=gocacheverify=1:令go命令繞過任何快取條目的使用,取而代之重新構建所有內容并檢查結果是否與現有的快取條目匹配,
  • GODEBUG=gocachehash=1:令go命令列印為其使用來構建快取查找鍵的所有內容哈希值的輸入,輸出是冗長的但能對除錯快取有用,
  • GODEBUG=gocachetest=1:令go命令列印其關于是否重用快取測驗結果的決策的詳細資訊,

environment主題——環境變數

go命令及其呼叫的工具查詢環境變數以進行配置,如果環境變數未設定,go命令使用一個合理的默認設定,要查看變數的有效設定,運行“go env ”,要修改默認設定,運行“go env -w =”,使用“go env -w”修改的默認值記錄在存盤在每個用戶一個的配置目錄中的Go環境變陣列態檔中,該目錄如同os.UserConfigDir所報告的,組態檔的位置可以通過設定環境變數GOENV修改,且“go env GOENV”列印有效的位置,但“go env -w”不能修改默認位置,詳細資訊參閱“go help env”,

通用的環境變數:

  • GCCGO:為“go build -compiler=gccgo”運行的gccgo命令,
  • GOARCH:要為之編譯代碼的體系結構或處理器,例如amd64、386、arm、ppc64,
  • GOBIN:“go install”安裝命令使用的目錄,
  • GOCACHE:go命令存盤快取資訊用以在將來的構建中重用的目錄,
  • GODEBUG:啟用多種除錯功能,詳細資訊參閱“go doc runtime”,
  • GOENV:Go環境變陣列態檔位置,不能使用“go env -w”設定,
  • GOFLAGS:一個空白分隔的-flag=value設定串列,當給定的標志被當前命令已知時,會被默認應用于go命令,每個條目必須是單獨的標志,因為條目是空白分隔的,標志值必須不包含空白,在命令列列出的標志在這個串列之后應用并因此覆寫之,
  • GOINSECURE:模塊路徑前綴的glob模式(以Go的path.Match的語法)的逗號分隔的串列,其應總是以不安全的方式拉取,只應用于被直接拉取的依賴,
  • GONOPROXY:見GOPRIVATE,
  • GONOSUMDB:見GOPRIVATE,
  • GOOS:要為之編譯代碼的作業系統,例如linux、darwin、windows、netbsd,
  • GOPATH:更新詳細資訊參閱:“go help gopath”,
  • GOPRIVATE:模塊路徑前綴的glob模式(以Go的path.Match的語法)的逗號分隔的串列,其應該總是直接拉取或不應該與校驗和資料庫比較,參閱“go help module-private”,
  • GOPROXY:Go模塊代理URL,參閱“go help modules”,
  • GOROOT:go樹的根,
  • GOSUMDB:使用的校驗和資料庫的名字,及可選地其公鑰和URL,參閱“go help module-auth”,
  • GOTMPDIR:go命令寫入臨時源檔案、包和二進制檔案的目錄,

與cgo一起使用的環境變數:

  • AR:當使用gccgo編譯器構建時用來操作庫歸檔檔案的命令,默認為“ar”,
  • CC:用來編譯C代碼的命令,
  • CGO_CFLAGS:當編譯C代碼時cgo將傳遞給編譯器的標志,
  • CGO_CFLAGS_ALLOW:一個正則運算式,用來指定允許出現在#cgo CFLAGS源代碼指令中的附加標志,不會應用于CGO_CFLAGS環境變數,
  • CGO_CFLAGS_DISALLOW:一個正則運算式,指定必須被禁止出現在#cgo CFLAGS源代碼指令中的標志,不會應用于CGO_CFLAGS環境變數,
  • CGO_CPPFLAGS:類似CGO_CFLAGS,但提供給C前處理器,
  • CGO_CPPFLAGS_ALLOW:類似CGO_CFLAGS_ALLOW,但提供給C前處理器,
  • CGO_CPPFLAGS_DISALLOW:類似CGO_CFLAGS_DISALLOW,但提供給C前處理器,
  • CGO_CXXFLAGS:類似CGO_CFLAGS,但提供給C++編譯器,
  • CGO_CXXFLAGS_ALLOW:類似CGO_CFLAGS_ALLOW,但提供給C++編譯器,
  • CGO_CXXFLAGS_DISALLOW:類似CGO_CFLAGS_DISALLOW,但提供給C++編譯器,
  • CGO_ENABLED:cgo命令是否支持,0或1,
  • CGO_FFLAGS:類似CGO_CFLAGS,但提供給Fortran編譯器,
  • CGO_FFLAGS_ALLOW:類似CGO_CFLAGS_ALLOW,但提供給Fortran編譯器,
  • CGO_FFLAGS_DISALLOW:類似CGO_CFLAGS_DISALLOW,但提供給Fortran編譯器,
  • CGO_LDFLAGS:類似CGO_CFLAGS,但提供給聯結器,
  • CGO_LDFLAGS_ALLOW:類似CGO_CFLAGS_ALLOW,但提供給聯結器,
  • CGO_LDFLAGS_DISALLOW:類似CGO_CFLAGS_DISALLOW,但提供給聯結器,
  • CXX:用來編譯C++代碼的命令,
  • FC:用來編譯Fortran代碼的命令,
  • PKG_CONFIG:pkg-config工具的路徑,

體系結構特定的環境變數:

  • GO386:對GOARCH=386,浮點指令集,有效值為387、sse2,
  • GOARM:對GOARCH=arm,要為之編譯的ARM體系結構,有效值為5、6、7,
  • GOMIPS:對GOARCH=mips{,le},是否使用浮點指令集,有效值為hardfloat(默認)、softfloat,
  • GOMIPS64:對GOARCH=mips64{,le},是否使用浮點指令集,有效值為hardfloat(默認)、softfloat,
  • GOWASM:對GOARCH=wasm,要使用的實驗性WebAssembly特性的逗號分隔的串列,有效值為satconv、signext,

特殊用途的環境變數:

  • GCCGOTOOLDIR:如果設定,表示在哪可以找到gccgo工具,例如cgo,默認值基于gccgo是怎么配置的,
  • GIT_ALLOW_PROTOCOL:由Git定義,允許與git fetch/clone一起使用的冒號分隔的方案(scheme)串列,如果設定,任何未明確提及的方案會被“go get”認為是不安全的,因為該變數是被Git定義,默認值不可以使用“go env -w”設定,
  • GO_EXTLINK_ENABLED:當與使用cgo的代碼一起使用-linkmode=auto時,聯結器是否應該使用外部鏈接模式,設為0禁用外部鏈接模式,1為啟用之,
  • GOROOT_FINAL:已安裝的Go樹的根,用在當其安裝在其構建位置以外的地方時,堆疊跟蹤中的檔案名從GOROOT重寫為GOROOT_FINAL,

從“go env”可獲得的附加資訊但不是從環境變數讀取的:

  • GOEXE:可執行檔案名后綴(在Windows上為“.exe”,在其它系統上為“”),
  • GOGCCFLAGS:提供給CC命令的空白分隔的引數串列,
  • GOHOSTARCH:Go工具鏈二進制檔案的體系結構(GOARCH),
  • GOHOSTOS:Go工具鏈二進制檔案的作業系統(GOOS),
  • GOMOD:主模塊的go.mod的絕對路徑,如果模塊感知模式啟用,但沒有go.mod,GOMOD將為os.DevNull(在類Unix系統上為“/dev/null”,在Windows上為“NUL”),如果模塊感知模式禁用,GOMOD將為空字串,
  • GOTOOLDIR:go工具(compile、cover、doc等等)安裝的目錄,

filetype主題——檔案型別

go命令檢查每個目錄中限定的一組檔案的內容,其根據檔案名的擴展名識別哪些檔案要檢查,這些擴展名為:

  • .c/.h:C源檔案,如果包使用cgo或SWIG,這些檔案將使用作業系統本地編譯器(通常為gcc)編譯;否則它們將觸發一個錯誤,
  • .cc/.cpp/.cxx/.hh/.hpp/.hxx:C++源檔案,只在使用cgo或SWIG時有用,并總是使用作業系統本地編譯器編譯,
  • .go:Go源檔案,
  • .m:Objective-C源檔案,只在使用cgo時有用,并總是使用作業系統本地編譯器編譯,
  • .s/.S:匯編源檔案,如果包使用cgo或SWIG,它們將使用作業系統本地匯編器(通常為gcc(sic))匯編;否則它們將使用Go匯編器匯編,
  • .swig/.swigcxx:SWIG定義檔案,
  • .syso:系統物件檔案,

這些型別除.syso之外的每個型別的檔案都可能包含構建約束,但go命令在檔案中不是空行或//-style行注釋的第一項處停止掃描構建約束,更多詳細資訊參閱go/build包檔案,

go.mod主題——go.mod檔案

模塊版本是由源檔案樹定義的,在其根目錄中有一個go.mod檔案,當go命令運行時,它查找當前目錄并然后查找相繼的父目錄來找出go.mod,go.mod標記主(當前)模塊的根,

go.mod檔案自身是面向行的,帶有//注釋但沒有/**/注釋,每行包含單個指令,由一個動詞后跟引陣列成,例如:

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:定義模塊路徑,
  • go:設定期望的語言版本,
  • require:依賴要求一個給定版本或之后的特定模塊,
  • exclude:從使用中排除特定模塊版本,
  • replace:以一個不同的模塊版本替代另一個模塊版本,

exclude和replace只應用在主模塊的go.mod,并在依賴中會被忽略,詳細資訊參閱https://research.swtch.com/vgo-mvs,

開頭的動詞可以被從相鄰的行中分解出來以創建一個塊,類似在Go import匯入中:

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

go.mod檔案被設計為既可以被直接編輯也可以容易地被工具更新,“go mod edit”命令可以被用來從程式和工具決議和編輯go.mod檔案,參閱“go help mod edit”,

go命令在每次其使用模塊圖時自動更新go.mod,以保證go.mod總是準確地反映實際情況并正確地格式化,例如,考慮該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

更新將重寫不規范的版本識別符號為語意版本(semver)格式,因此A的v1變成v1.0.0,E的dev變成dev分支上最后提交的偽版本號,可能為v0.0.0-20180523231146-b3f5c0f6e5f1,

更新將修改依賴要求規則以遵守排除規則,因此在已經排除的D v1.2.3上的依賴要求被更新為使用D的下一個可獲得的版本號,可能為D v1.2.4或D v1.3.0,

更新將洗掉冗余的或誤導性的依賴要求,例如,如果A v1.0.0自身依賴要求B v1.2.0和C v1.0.0,那么go.mod的B v1.0.0依賴要求是誤導性的(被A對v1.2.0的需求所取代),且其C v1.0.0的依賴要求是冗余的(被A對相同版本的需求所暗指),因此它們都會被洗掉,如果模塊M包含從B或C直接匯入包的包,那么依賴要求將被保留但更新為使用的實際版本號,

最后,更新將以規范的格式重新格式化go.mod,以使將來機械般的修改也將導致最小的差異,

因為模塊圖定義了import陳述句的含義,任何加載包的命令也會使用并因此更新go.mod,包括go build、go get、go install、go list、go test、go mod graph、go mod tidy、go mod why,

由go指令設定的期望的語言版本決定了當編譯模塊時哪些語言特性可獲得,在該版本可用的語言特性將可以使用,在早期版本移除的或在后續版本添加的語言特性將不可獲得,注意語言版本不影響構建標志,它是由使用的Go發布版本決定的,

gopath主題——GOPATH環境變數

GOPATH用于決議import陳述句,其被go/build包實作并在go/build包中記錄檔案,

GOPATH環境變數列出查找Go代碼的位置,在Unix上,值是冒號分隔的字串,在Windows上,值是分號分隔的字串,在Plan 9上,值是一個串列,

如果環境變數未設定,GOPATH默認為在用戶的主目錄中名字為“go”的子目錄(在Unix上為$HOME/go,在Windows上為%USERPROFILE%\go),除非該目錄包含Go發行版,運行“go env GOPATH”來查看當前的GOPATH,

參閱https://golang.org/wiki/SettingGOPATH來設定自定義GOPATH,

GOPATH中列出的每個目錄必須有規定的結構:

src目錄包含源代碼,src下的路徑決定import路徑或可執行檔案名,

pkg目錄包含安裝的包物件檔案,如同在Go樹中,每個目標作業系統和體系結構對都有其自己的pkg子目錄(pkg/GOOS_GOARCH),

如果DIR是GOPATH中列出的一個目錄,源代碼在DIR/src/foo/bar中的包可以被匯入為“foo/bar”并且其編譯形式的檔案會被安裝到“DIR/pkg/GOOS_GOARCH/foo/bar.a”,

bin目錄包含編譯的命令,每個命令以其源代碼目錄命名,但只取最后一個元素,不是全部的路徑,亦即,源代碼在DIR/src/foo/quux中的命令被安裝至DIR/bin/quux,而不是DIR/bin/foo/quux,“foo/”前綴被剝掉,因此你可以添加DIR/bin至你的PATH中來訪問安裝的命令,如果GOBIN環境變數被設定,命令會被安裝至其命名的目錄而不是DIR/bin,GOBIN必須為絕對路徑,

這是一個示例目錄布局:

GOPATH=/home/user/go

/home/user/go/
	src/
		foo/
			bar/       (bar包中的go代碼)
			    x.go
			quux/      (main包中的go代碼)
				y.go
	bin/
		quux           (安裝的命令)
	pkg/
		linux_amd64/
			foo/
				bar.a  (安裝的包物件檔案)

go搜索GOPATH中列出的每個目錄來查找源代碼,但新的包總是下載至串列中的第一個目錄,

示例參閱https://golang.org/doc/code.html,

GOPATH和模塊

當使用模塊時,GOPATH不再用來決議import匯入,然而,其仍然會被用來保存下載的源代碼(在GOPATH/pkg/mod中)和編譯的命令(在GOPATH/bin中),

internal目錄

在名為“internal”目錄中或以下的代碼只可以被以“internal”的父目錄為根的目錄樹中的代碼匯入,這是上面的目錄布局擴展版本:

/home/user/go/
	src/
		crash/
			bang/         (bang包中的go代碼)
				b.go
		foo/              (foo包中的go代碼)
			f.go
			bar/          (bar包中的go代碼)
				x.go
			internal/
				baz/      (baz包中的go代碼)
					z.go
			quux/         (main包中的go代碼)
				y.go

z.go中的代碼被匯入為“foo/internal/baz”,但該import匯入陳述句只能出現在以foo為根的子樹中的源檔案中,源檔案foo/f.go、foo/bar/x.go、foo/quux/y.go都可匯入“foo/internal/baz”,但源檔案crash/bang/b.go不可以,

細節參閱https://golang.org/s/go14internal,

vendor目錄

go 1.6包含使用外部依賴的本地副本的支持,以滿足那些依賴的匯入,通常被稱為使用vendor(vendoring),

在名為“vendor”目錄以下的代碼只可以被以“vendor”的父目錄為根的目錄樹中的代碼匯入,并且只使用忽略直到并包括vendor元素前綴的匯入路徑,

這是從上一小節來的例子,但“internal”目錄重命名為“vendor”并且添加了一個新的foo/vendor/crash/bang目錄:

/home/user/go/
	src/
		crash/
			bang/              (bang包中的代碼)
				b.go
		foo/                   (foo包中的代碼)
			f.go
			bar/               (bar包中的代碼)
				x.go
			vendor/
				crash/
					bang/      (bang包中的代碼)
						b.go
				baz/           (baz包中的代碼)
					z.go
			quux/              (main包中的代碼)
				y.go

應用和internal相同的可見性規則,但在z.go中的代碼匯入為“baz”,而不是“foo/vendor/baz”,

在源代碼樹中較深的vendor目錄中的代碼隱藏在較高目錄中的代碼,在以foo為根的子樹中“crash/bang”的匯入決議為“foo/vendor/crash/bang”,而不是最頂層的“crash/bang”,

vendor目錄中的代碼不受匯入路徑檢查的影響(參閱“go help importpath”),

當“go get”檢出或更新git倉庫時,其現在也更新子模塊,

vendor目錄不影響第一次被“go get”檢出的新倉庫的位置:它們總是放置在主GOPATH中,從不在vendor子樹中,

細節參閱https://golang.org/s/go15vendor,

gopath-get主題——遺留的GOPATH的go get

go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages]

“go get”命令根據go命令運行在模塊感知模式還是遺留的GOPATH模式來改變行為,這里的幫助文本,即使在模塊感知模式也可作為“go help gopath-get”訪問,描述“go get”在遺留的GOPATH模式下的操作,

get下載由匯入路徑指定名字的包,以及它們的依賴,然后安裝指定名字的包,類似“go install”,

標志:

  • -d:在下載包之后停止;亦即,其令get不安裝包,
  • -f:只在-u被設定時有效,強制get -u不驗證每個包都是從其匯入路徑隱含的源代碼控制倉庫檢出,如果源代碼是源的本地fork分支這將會有用,
  • -fix:在決議依賴和構建代碼之前在已下載的包上運行fix工具,
  • -insecure:允許使用如HTTP等不安全的方案,從倉庫拉取以及決議自定義域名,謹慎使用,
  • -t:同時下載指定的包構建測驗所需的包,
  • -u:使用網路來更新指定名字的包及其依賴,默認情況下,get使用網路來檢出缺少的包但不會使用它來查找已存在包的更新,
  • -v:啟用詳細的進度和除錯輸出,

get也接受構建標志來控制安裝,參閱“go help build”,

當檢出一個新包時,get創建目標目錄GOPATH/src/,如果GOPATH包含多個入口,get使用第一個,更多詳細資訊參閱:“go help gopath”,

當檢出或更新包時,get查找匹配Go本地安裝版本的分支(branch)或標簽(tag),最重要的規則是,如果本地安裝正在運行版本“go1”,get查找名字為“go1”的分支或標簽,如果沒有這樣的版本存在,其檢索包的默認分支,

當go get檢出或更新一個Git倉庫,其也會更新被該倉庫參考的任何git子模塊,

get從不檢出或更新在vendor目錄中存盤的代碼,

關于指定包的更多資訊,參閱“go help packages”,

關于“go get”如何查找下載的源代碼的更多資訊,參閱“go help importpath”,

這段文字描述當使用GOPATH來管理源代碼和依賴時get的行為,如果相反go命令運行在模塊感知模式,“go help get”的內容會不同,類似地,get的標志和行為的細節也會改變,參閱“go help modules”和“go help module-get”,

參閱:go build、go install、go clean,

goproxy主題——模塊代理協議

Go模塊代理是能回應特定格式URL的GET請求的任何web服務器,請求沒有查詢(query)引數,因此即使從固定檔案系統(包括file://URL)提供服務的站點也能成為模塊代理,

發送至Go模塊代理的GET請求為:

  • GET $GOPROXY//@v/list:回傳給定模塊的所有已知版本的串列,一行一個,
  • GET $GOPROXY//@v/.info:回傳關于給定模塊給定版本的JSON格式的元資料,
  • GET $GOPROXY//@v/.mod:回傳給定模塊給定版本的go.mod檔案,
  • GET $GOPROXY//@v/.zip:回傳給定模塊給定版本的zip歸檔檔案,
  • GET $GOPROXY//@latest:以與/@v/.info相同的格式回傳關于給定模塊最后的已知版本的JSON格式的元資料,最后的版本應該為如果/@v/list為慷訓者沒有列出的版本是合適的時候go命令可以使用的模塊版本,/@latest是可選的且可能不被模塊代理實作,

當決議模塊的最后版本時,go命令將請求/@v/list,然后,如果沒有發現合適的版本,則請求/@latest,go命令偏向于,按順序為:語意上最高的發布版本,語意上最高的預發布版本,按時間順序最近的偽版本,在Go 1.12及更早,go命令認為/@v/list中的偽版本為預發布版本,但從Go 1.13起不再這樣,

為了避免從大小寫敏感的檔案系統提供服務時的問題,元素進行大小寫編碼,以一個感嘆號后跟對應的小寫字母替換每個大寫字母:github.com/Azure編碼為github.com/!azure,

給定模塊的JSON格式的元資料對應此Go資料結構,其可能在將來擴展:

type Info struct {
    Version string    // 版本字串
    Time    time.Time // 提交(commit)時間
}

給定模塊給定版本的zip歸檔檔案是標準的zip檔案,其包含對應于模塊的源代碼和相關的檔案的檔案樹,歸檔檔案使用斜杠分隔的路徑,歸檔檔案中每個檔案路徑必須以@/開始,其中module和version是直接替換的,不進行大小寫編碼,模塊檔案樹的根對應于歸檔檔案中的@/前綴,

即使從版本控制系統直接下載時,go命令也合成顯式的info、mod和zip檔案,并將它們存盤在其本地快取$GOPATH/pkg/mod/cache/download,如同從代理直接下載它們一樣,快取的布局與代理URL空間相同,因此在$GOPATH/pkg/mod/cache/download提供服務(或拷貝其至)https://example.com/proxy能令其它用戶以GOPROXY=https://example.com/proxy訪問那些快取的模塊版本,

importpath主題——import路徑語法

匯入路徑(參閱“go help packages”)表示存盤在本地檔案系統的包,通常,匯入路徑表示或者標準包(如“unicode/utf8”)或者在其中一個作業空間(譯注:其概念可參考 相對匯入路徑 小節)找到的包(更多細節參閱:“go help gopath”),

相對匯入路徑

以./或../開頭的匯入路徑稱為相對路徑,工具鏈以兩種方式支持相對匯入路徑作為快捷方式,

第一種,相對路徑可以用作命令列上的速記,如果你作業在包含以“unicode”匯入的代碼的目錄中并想為“unicode/utf8”運行測驗,你可以輸入“go test ./utf8”而不需要指定完整的路徑,同樣地,在相反的情況下,“go test ..”將從“unicode/utf8”目錄測驗“unicode”,相對模式也是允許的,如“go test ./...”用來測驗所有子目錄,關于模式語法的詳細資訊參閱“go help packages”,

第二種,如果你不是在作業空間中編譯Go程式,你可以在該程式import匯入陳述句中使用相對路徑來參考附近同樣不在作業空間中的代碼,這更易于在通常的作業空間外試驗使用小型的多包程式,但這種程式不能用“go install”來安裝(沒有作業空間來安裝它們),因此每次它們被構建都會從頭開始重新構建,為了避免歧義,Go程式不可以在作業空間中使用相對匯入路徑,

遠程匯入路徑

某些匯入路徑也描述了如何使用版本控制系統為包獲取源代碼,

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

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"

對于托管在其它服務器上的代碼,匯入路徑或者用版本控制型別限定,或者go工具可以通過http/https動態地拉取該匯入路徑并從HTML中的一個<meta>標簽發現代碼的所在,

要宣告代碼的位置,repository.vcs/path格式的匯入路徑指定給出的倉庫,可帶或不帶.vcs后綴(譯注:見支持的版本控制系統),使用指定名字的版本控制系統,然后是該倉庫中的路徑,支持的版本控制系統為:

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

例如,import "example.org/user/foo.hg"表示在example.org/user/foo或foo.hg的Mercurial倉庫的根目錄,import "example.org/repo.git/foo/bar"表示在example.org/repo或repo.git的Git倉庫的foo/bar目錄,

當版本控制系統支持多種協議時,在下載時每一種會輪流嘗試,例如,Git下載嘗試https://,然后git+ssh://,

默認情況下,下載限于已知的安全協議(例如https、ssh),要為Git下載覆寫該設定,可以設定GIT_ALLOW_PROTOCOL環境變數(更多細節參閱:“go help environment”),

如果匯入路徑不是已知的代碼托管站點且也缺少版本控制限定符,go工具嘗試通過https/http拉取匯入路徑并在檔案的HTML 中查找<meta>標簽,

meta標簽有如下格式:

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

import-prefix是和倉庫根對應的匯入路徑,其必須為用“go get”抓取的包的前綴或完全匹配,如果其不是完全匹配,會對前綴生成另一個http請求來驗證<meta>標簽是匹配的,

meta標簽應該盡可能早地在檔案中出現,特別地,其應該在任何原始的JavaScript或CSS之前出現,以避免迷惑go命令的受限的決議器,

vcs是“bzr”、“fossil”、“git”、“hg”、“svn”之一,

repo-root是包含方案但不包含.vcs限定符的版本控制系統的根,

例如,import "example.org/pkg/foo"將導致以下請求:

https://example.org/pkg/foo?go-get=1 (首選的)
http://example.org/pkg/foo?go-get=1  (備選的,只與-insecure一起)

(譯注:假設該頁面的請求為https://example.org/exproj?go-get=1)如果該頁面包含meta標簽<meta name="go-import" content="example.org git https://code.org/r/p/exproj">,go工具將驗證https://example.org/?go-get=1包含相同的meta標簽,并然后git clone https://code.org/r/p/exproj進GOPATH/src/example.org,

當使用GOPATH時,下載的包被寫入至在GOPATH環境變數中列出的第一個目錄,(參閱“go help gopath-get”和“go help gopath”,)

當使用模塊時,下載的包存盤在模塊快取中,(參閱“go help module-get”和“go help goproxy”,)

當使用模塊時,go-import meta標簽一個額外的變數會被識別,且勝于那些列出版本控制系統的變數,該變數使用“mod”作為內容值中的vcs,如同:

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

該標簽表示用以example.org開頭的路徑從URL為https://code.org/moduleproxy上可用的模塊代理拉取模塊,關于代理協議的詳細資訊參閱“go help goproxy”,

匯入路徑檢查

當如上所述的自定義匯入路徑功能重定向至已知的代碼托管站點時,每個結果包都有兩個可能的匯入路徑,使用自定義域名或已知的托管站點,

如果package陳述句后立即跟著(在下一個新行之前)這兩種格式之一的注釋,則被稱為帶有“匯入注釋”(import comment):

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

go命令會拒絕安裝帶有匯入注釋的包,除非包是被匯入注釋中的匯入路徑參考的,用這種辦法,匯入注釋讓包作者確保使用自定義匯入路徑而不是指向底層代碼托管站點的直接路徑,

對在vendor目錄樹中找到的代碼匯入路徑檢查是禁用的,這令拷貝代碼進vendor目錄樹中的備用位置而無需更新匯入注釋成為可能,

當使用模塊時匯入路徑檢查也是禁用的,匯入路徑注釋被go.mod檔案中的module陳述句所淘汰,

更多細節參閱https://golang.org/s/go14customimport,

modules主題——模塊,模塊版本,及更多

模塊是關聯的Go包的集合,模塊是源代碼交換和版本控制的單元,go命令對使用模塊作業有直接支持,包括記錄和解決對其它模塊的依賴,模塊替代舊的基于GOPATH的方法來指定在給定的構建中使用哪些源檔案,

模塊支持

go命令包含對Go模塊的支持,每當go.mod檔案在當前目錄或當前目錄某個父目錄中找到時,模塊感知模式默認是激活的,

利用模塊支持最快的方式是檢出你的倉庫,在那創建go.mod檔案(在下一節中描述),在該檔案樹中運行go命令,

對于更多細粒度的控制,go命令繼續遵守臨時環境變數GO111MODULE,其可以被設定為三個字串值之一:off、on或auto(默認值),如果GO111MODULE=on,那么go命令要求使用模塊,從不參考GOPATH,我們稱之為命令是模塊感知的或運行在“模塊感知模式”,如果GO111MODULE=off,那么go命令從不使用模塊支持,相反其搜索vendor目錄和GOPATH來查找依賴;我們現在稱之為“GOPATH模式”,如果GO111MODULE=auto或未設定,那么go命令基于當前目錄來啟用或禁用模塊支持,只在當前目錄包含go.mod檔案或在包含go.mod檔案的目錄之下時,模塊支持才啟用,

在模塊感知模式,GOPATH不再在構建期間定義匯入的含義,但其仍然存盤下載的依賴(在GOPATH/pkg/mod中)和安裝的命令(在GOPATH/bin中,除非GOBIN被設定),

定義模塊

模塊被在樹的根目錄中有go.mod檔案的Go源檔案樹所定義,包含go.mod檔案的目錄被稱為模塊根,典型地,模塊根也對應于源代碼倉庫根(但一般來說不需要),模塊是在模塊根及其子目錄中的所有Go包的集合,但不包括有其自己的go.mod檔案的子樹,

“模塊路徑”是對應于模塊根的匯入路徑前綴,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檔案也可以指定只在直接構建模塊時應用的替代和排除的版本;當模塊合并至更大的構建時它們會被忽略,更多關于go.mod檔案,參閱“go help go.mod”,

要啟動一個新模塊,只需要在模塊的目錄樹的根創建go.mod檔案,其中只包含模塊宣告,“go mod init”命令可以用來做此事:

go mod init example.com/m

在一個已使用如godep、glide、dep等現存的依賴管理工具的專案中,“go mod init”也會添加匹配已有配置的require陳述句,

一旦go.mod檔案存在,不需要額外的步驟:諸如“go build”、“go test”甚至“go list”等go命令會根據需要自動地添加新的依賴來滿足匯入,

主模塊和構建串列

“主模塊”是包含go命令運行的目錄的模塊,go命令通過在當前目錄、或當前目錄的父目錄、或父目錄的父目錄等等,搜索go.mod來查找模塊根,

主模塊的go.mod檔案通過require、replace和exclude陳述句,定義了被go命令可用的包的精確集合,通過require陳述句后找到的依賴模塊也影響該包集合的定義,但只通過其go.mod檔案的require陳述句:在依賴模塊中的任何replace和exclude陳述句都會被忽略,因此replace和exclude陳述句允許主模塊完全控制其自身構建,不會也服從于依賴的完全控制,

提供要構建包的模塊集合被稱為“構建串列”,構建串列最初只包含主模塊,然后go命令將被已在串列中的模塊依賴要求的精確模塊版本添加到串列中,遞回地操作,直到沒有可添加至串列中,如果特定模塊的多個版本被添加至串列中,那么最后只有最后的版本(基于語意版本排序)保留以用于構建中,

“go list”命令提供關于主模塊和構建串列的資訊,例如:

go list -m              # 列印主模塊的路徑
go list -m -f={{.Dir}}  # 列印主模塊的根目錄
go list -m all          # 列印構建串列

維護模塊依賴要求

go.mod檔案對程式員和工具都意味著可讀的和可編輯的,go命令自身自動地更新go.mod檔案來維護標準的格式和require陳述句的準確性,

任何發現陌生import的go命令會查找包含該import的模塊并自動地添加該模塊的最后版本至go.mod,因此,在大多數情況下,添加import至源代碼并運行“go build”、“go test”甚至“go list”足以:作為分析包的一部分,go命令將發現并決議該import并更新go.mod檔案,

即使是在只考慮模塊中單個包時,go命令也可以決定一個模塊依賴要求是缺少的且必須被添加,另一方面,決定一個模塊依賴要求不再需要且可以被洗掉要求得到模塊中所有包的全貌,遍及所有可能的構建配置(體系結構、作業系統、構建標志,等等),“go mod tidy”命令生成該全貌并然后添加任何缺少的模塊依賴要求及洗掉不需要的,

作為維護go.mod中require陳述句的一部分,go命令跟蹤哪些提供被當前模塊直接匯入的包,及哪些提供被其它模塊依賴間接使用的包,在go.mod檔案中,只被間接使用所需的依賴要求以“// indirect”注釋標記,一旦被其它直接依賴要求隱含,間接依賴要求會被自動從go.mod檔案中洗掉,間接依賴要求只出現在當使用無法說明其自身某些依賴的那些模塊,或當顯式地升級模塊的依賴至領先其自身宣告的依賴要求,

因為這樣的自動維護,go.mod中的資訊是構建的最新的、可讀的描述,

“go get”命令更新go.mod來修改在構建中使用的模塊版本,一個模塊的升級可能隱含升級其它的,并同樣地一個模塊的降級可能隱含地降級其它的,“go get”命令也會進行這些隱含的修改,如果go.mod被直接修改,類似“go build”或“go list”等命令將假設升級是有意的,并自動地進行所有隱含的升級,并更新go.mod來反映之,

“go mod”命令提供其他用于維護和理解模塊及go.mod檔案的功能,參閱“go help mod”,

-mod構建標志提供對更新和使用go.mod的額外控制,

  • 如果以-mod=mod呼叫,即使存在vendor目錄go命令也從模塊快取加載模塊,
  • 如果以-mod=readonly呼叫,go命令不允許go.mod如上所述的隱式自動更新,相反,當需要對go.mod的任何修改時,其會失敗,該設定用來檢查go.mod不需要更新是最有用的,例如在持續集成和測驗系統中,即使使用-mod=readonly,“go get”命令仍然允許更新go.mod,且“go mod”命令不使用-mod標志(或任何其它構建標志),
  • 如果以-mod=vendor呼叫,go命令假設vendor目錄包含依賴的正確拷貝并忽略在go.mod中的依賴描述,

偽版本

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命令會接受提交哈希值并自動地翻譯其為偽版本(或如果可用的話為打標簽的版本),該轉換是模塊查詢的一個例子(譯注:參閱 模塊查詢 小節),

模塊查詢

在命令列中和主模塊的go.mod檔案中go命令都接受“模塊查詢”來替代模塊版本,(在評估主模塊的go.mod檔案中找到的查詢之后,go命令更新檔案以用其結果代替查詢),

完全指定的語意版本,如“v1.2.3”,評估為該指定的版本,

語意版本前綴,如“v1”或“v1.2”,評估為帶該前綴的最后可用的打標簽的版本,

語意版本比較,如“<v1.2.3”或“>=v1.5.6”,評估為最接近比較目標的可用的打標簽的版本(對<和<=為最后的版本,對>和>=為最早的版本),

字串“latest”匹配最后的可用的打標簽的版本,否則的話為底層源代碼倉庫的最后的未打標簽的修訂,

字串“upgrade”類似“latest”,但如果模塊當前依賴要求比“latest”會選擇的版本更后的版本(例如,較新的預發布版本),“upgrade”將反而選擇較后的版本,

字串“patch”匹配與當前依賴要求的版本有相同的主、次版本號的模塊的最后的可用的打標簽的版本,如果當前沒有依賴要求版本,“patch”等同于“latest”,

底層源代碼倉庫的修訂識別符號,例如提交哈希前綴、修訂標簽、分支名,將選擇該特定的代碼修訂,如果修訂識別符號還用于語意版本打標簽,則查詢評估為該語意版本,否則查詢評估為提交的偽版本,注意帶有被其它查詢語法匹配的名字的分支和標簽不能以這種方式被選擇,例如,查詢“v2”表示以“v2”開頭的最后的版本,不是名字為“v2”的分支,

查詢偏向于發布版本而非預發布版本,例如,“<v1.2.3”會偏向于回傳“v1.2.2”而不是“v1.2.3-pre1”,即使“v1.2.3-pre1”更靠近比較目標,

被主模塊的go.mod中的exclude陳述句禁止的模塊版本被認為是不可用的且不會被查詢回傳,

例如,這些命令全是有效的:

go get github.com/gorilla/mux@latest    # 相同(@latest是“go get”的默認值)
go get github.com/gorilla/[email protected]    # 記錄為v1.6.2
go get github.com/gorilla/mux@e3702bed2 # 記錄為v1.6.2
go get github.com/gorilla/mux@c856192   # 記錄為v0.0.0-20180517173623-c85619274f5d
go get github.com/gorilla/mux@master    # 記錄master的當前含義

模塊兼容性和語意版本控制

go命令要求模塊使用語意版本并期望版本準確描述兼容性:其假設v1.5.4是對v1.5.3、v1.4.0甚至v1.0.0后向兼容的替代,更通常地go命令期望包遵守“匯入兼容性規則”,表述為:

“如果舊的包和新的包有相同的匯入路徑,新的包必須和舊的包后向兼容,”

因為go命令假設了匯入兼容性規則,模塊定義只能設定其依賴之一的最低依賴要求版本:其不能設定最高的或排除選擇的版本,不過,匯入兼容性規則不是保證:可能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,以這種方式在模塊路徑和匯入路徑中包含主版本號稱為“語意匯入版本控制”,主版本為v2或更后的模塊的偽版本以該主版本開頭,而不是v0,就如v2.0.0-20180326061214-4fc5987536ef,

作為一個特殊情況,以gopkg.in/開頭的模塊路徑繼續使用在該系統上建立的約定:主版本總是出現,且其前面是點號而不是斜杠:gopkg.in/yaml.v1和gopkg.in/yaml.v2,而非gopkg.in/yaml和gopkg.in/yaml/v2,

go命令將帶有不同模塊路徑的模塊視為無關的:其不會在example.com/m和example.com/m/v2之間建立關聯,帶有不同主版本的模塊可以在構建中一起使用,并因為事實上它們的包使用不同的匯入路徑而保持分離,

在語意版本控制中,主版本v0用于最初的開發,表示沒有穩定性或后向兼容性的期望,主版本v0不會出現在模塊路徑中,因為那些版本是為v1.0.0準備的,且v1也不會出現在模塊路徑中,

在語意匯入版本控制約定引入之前撰寫的代碼,可能使用主版本v2或更后的來描述如同在v0和v1中使用的不帶版本的匯入路徑的相同集合,為了顧及這樣的代碼,如果源代碼倉庫對沒有go.mod的檔案樹有v2.0.0或更后的標簽,版本被認為是v1模塊的可用的版本的一部分,且轉換為模塊版本時給出一個+incompatible后綴,如同v2.0.0+incompatible,+incompatible標簽也會應用于從這種版本產生的偽版本,如同v2.0.1-0.yyyymmddhhmmss-abcdefabcdef+incompatible,

通常,在構建串列(如同“go list -m all”所報告)中有對v0版本、預發布版本、偽版本、+incompatible版本的依賴,預示著當升級依賴時更可能出問題,因為對它們沒有兼容性期望,

關于語意匯入版本控制的更多資訊參閱https://research.swtch.com/vgo-import,關于語意版本控制的更多資訊參閱https://semver.org/,

模塊代碼布局

目前,關于如何將版本控制系統中的源代碼映射到模塊檔案樹的資訊參閱https://research.swtch.com/vgo-module,

模塊下載和校驗

根據GOPROXY環境變數(參閱“go help env”)的設定,go命令可以從代理或直接連接到源代碼控制服務器來拉取模塊,GOPROXY的默認設定為“https://proxy.golang.org,direct”,表示嘗試從Google運行的Go模塊鏡像,且如果代理報告其沒有該模塊(HTTP錯誤404或410)則退回直接連接,關于服務的隱私政策參閱https://proxy.golang.org/privacy,如果GOPROXY設定為字串“direct”,下載使用到源代碼控制服務器的直接連接,設定GOPROXY為“off”禁止從任何來源下載模塊,否則,GOPROXY期望為模塊代理URL的逗號分隔的串列,在這種情況下go命令將從那些代理拉取模塊,對每個請求,go命令依次嘗試每個代理,只在如果當前代理回傳404或410的HTTP回應時才移動至下一個,字串“direct”可以出現在代理串列中,令到在搜索中該查找點嘗試直接的連接,任何在“direct”之后列出的代理從不會被查詢,

GOPRIVATE和GONOPROXY環境變數允許為選擇的模塊繞過代理,詳細資訊參閱“go help module-private”,

不管模塊的來源是什么,go命令都會將下載結果與已知的校驗和校對,來發現任何特定模塊版本的內容中從這一天到下一天未預期的改變,該校對首先查看當前模塊的go.sum檔案,但會回退至Go校驗和資料庫,其由GOSUMDB和GONOSUMDB環境變數控制,詳細資訊參閱“go help module-auth”,

關于代理協議以及快取的下載包格式的詳細資訊參閱“go help goproxy”,

模塊和使用vendor

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

默認情況下,go命令通過從其源下載模塊并使用那些下載的副本(在校驗之后,如之前的小節所描述)來滿足依賴,為了允許與Go的較舊版本互操作,或者為了確保構建使用的所有檔案在單獨的檔案樹中保存在一起,“go mod vendor”在主模塊的根目錄創建名字為vendor的目錄,并在該處存盤依賴模塊的所有包,它們需要用來支持構建和測驗主模塊中的包,

要使用主模塊的頂級vendor目錄來滿足依賴以進行構建(禁止使用通常的網路源和本地快取),使用“go build -mod=vendor”,注意只有主模塊的頂層vendor目錄才被使用;在其他位置的vendor目錄仍然被忽略,

module-get主題——模塊感知的go get

(譯注:該主題介紹使用模塊管理源代碼和依賴的行為,亦即 go get——添加依賴包至當前模塊并安裝之 小節的內容,使用GOPATH的行為描述于 gopath-get主題——遺留的GOPATH的go get 小節,)

module-auth主題——使用go.sum的模塊校驗

go命令嘗試校驗每個下載的模塊,檢查今天為特定模塊版本下載的位元是否匹配昨天下載的位元,這確保可重復的構建并發現意想不到的修改的引入,無論是否惡意,

在每個模塊的根,和go.mod一起,go命令維護一個名字為go.sum的檔案,其包含模塊依賴的加密校驗和,

go.sum中每行的格式為三個欄位:

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

每個已知的模塊版本在go.sum檔案中產生兩行,第一行給出模塊版本的檔案樹的哈希,第二行附加“/go.mod”至版本version后并給出僅限于模塊版本的(可能是合成的)go.mod檔案的哈希,僅限于go.mod的哈希允許下載和校驗用來計算依賴圖的模塊版本的go.mod檔案,不用也下載所有模塊的源代碼,

哈希hash以格式為“h:”的演算法前綴開頭,唯一定義的演算法前綴為“h1:”,其使用SHA-256,

模塊校驗失敗

go命令維護一份下載的包的快取,并在下載時計算和記錄每個包的加密校驗和(譯注:可能位于$GOPATH/pkg/mod/cache/download//@v/.ziphash),在一般的操作中,go命令將主模塊的go.sum檔案和這些預先計算的校驗和校對,而非在每次命令呼叫時重新計算之,“go mod verify”命令檢查模塊下載的快取副本仍然匹配其記錄的校驗和及go.sum中的條目,

在日常的開發中,給定模塊版本的校驗和應該從不改變,每次依賴被給定的主模塊使用時,go命令將其本地快取副本——無論是否新近下載——與主模塊的go.sum校對,如果校驗和不匹配,go命令報告該不匹配為安全錯誤并拒絕運行構建,當此發生時,謹慎繼續行事:代碼意外地修改意味著今天的構建將不會匹配昨天的,且意外的修改不可能是有用的,

如果go命令報告go.sum中的不匹配,為報告的模塊版本下載的代碼則不匹配在主模塊之前的構建中使用的那些代碼,在此刻找出正確的校驗和是什么是很重要的,來決定go.sum是錯的還是下載的代碼是錯誤,通常go.sum是正確的:你希望使用與你昨天使用相同的代碼,

如果下載的模塊還未在go.sum中被包含且其為公共可用的模塊,go命令查詢Go校驗和資料庫來拉取期望的go.sum行,如果下載的代碼不匹配那些行,go命令報告該不匹配并退出,注意對已經在go.sum中列出的模塊版本不再查詢資料庫,

如果報告了go.sum不匹配,總是值得調查為什么今天下載的代碼與昨天下載的不同,

GOSUMDB環境變數標記了使用的校驗和資料庫名字及可選地其公鑰和URL,如同:

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

go命令知道sum.golang.org的公鑰,并且名字sum.golang.google.cn(在中國大陸中可用)連接至sum.golang.org校驗和資料庫;使用任何其它的資料庫要求顯式地給出公鑰,URL默認為“https://”后跟資料庫名字,

GOSUMDB默認為“sum.golang.org”,為被Google運行的Go校驗和資料庫,關于服務的隱私政策參閱https://sum.golang.org/privacy,

如果GOSUMDB設定為“off”,或如果“go get”以-insecure標志呼叫,不會查詢校驗和資料庫,并且接受所有未識別的模塊,以放棄驗證對所有模塊的可重復下載的安全保證作為代價,對特定模塊繞過校驗和資料庫的更好方式為使用GOPRIVATE或GONOSUMDB環境變數,詳細資訊參閱“go help module-private”,

“go env -w”命令(參閱“go help env”)可以用來為以后的go命令呼叫設定這些環境變數,

module-private主題——非公共模塊的模塊配置

go命令默認從proxy.golang.org上的公共Go模塊鏡像下載模塊,無論來源是什么,其也默認將下載的模塊與sum.golang.org上的公共Go校驗和資料庫校驗,對公開可獲得的源代碼這些默認行為作業得很好,

GOPRIVATE環境變數控制哪些模塊go命令認為是私有的(不是公開可獲得的)并應該因此不使用代理或校驗和資料庫,變數是模塊路徑前綴的glob模式(以Go的path.Match的語法)的逗號分隔的串列,例如,

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

其令go命令將帶有匹配任一模式的路徑前綴的任何模塊視為私有,包括git.corp.example.com/xyzzy、rsc.io/private、rsc.io/private/quux,

GOPRIVATE環境變數可能也會被其它工具使用來標記非公共模塊,例如,編輯器可以使用GOPRIVATE來決定是否將包import超鏈接至godoc.org頁面,

為了對模塊下載和校驗進行細粒度的控制,GONOPROXY和GONOSUMDB接受相同型別的glob串列,并覆寫GOPRIVATE以分別地對是否使用代理和校驗和資料庫作特定的決定,

例如,如果公司運行了一個提供私有模塊服務的模塊代理,用戶可以如下使用來配置go:

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

這將告訴go命令和其它工具以corp.example.com子域名開頭的模塊是私有的,但對下載公共和私有模塊都應使用公司代理,因為GONOPROXY已被設定為不會匹配任何模塊的模式,從而覆寫GOPRIVATE,

“go env -w”命令(參閱“go help env”)可以用來為以后的go命令呼叫設定這些環境變數,

packages主題——包串列和模式

許多命令應用于一個包集合:

go action [packages]

通常,[packages]是匯入路徑的串列,

為根路徑或以.或..元素開頭的匯入路徑被決議為檔案系統路徑并表示該目錄中的包,

否則,對某些在GOPATH環境變數中列出的DIR,匯入路徑P表示DIR/src/P目錄中找到的包(更多詳細資訊參閱:“go help gopath”),

如果沒有給出匯入路徑,操作應用于當前目錄中的包,

路徑有四個保留的名字不應該用于使用go工具進行構建的包:

  • “all”:擴展為所有GOPATH樹中找到的所有包,例如,“go list all”列出本地系統上的所有包,當使用模塊時,“all”擴展為主模塊及其依賴中的所有包,包括其中任何的測驗所需的依賴,
  • “cmd”:擴展為Go倉庫的命令及其內部庫,
  • “main”:表示獨立的可執行檔案中的頂層包,
  • “std”:類似all但只擴展為標準Go庫中的包,

以“cmd/”開頭的匯入路徑只匹配Go倉庫中的源代碼,

匯入路徑是一個模式如果其包含一個或多個“...”通配符,其中每個都可以匹配任何字串,包括空字串和含斜杠的字串,這樣的模式擴展為GOPATH樹中找到的名字匹配模式的所有包目錄,

為了令常見的模式更方便,有兩種特殊情況,第一種,模式末尾的/...可以匹配空字串,因此net/...匹配net和在其子目錄中的包,如net/http,第二種,任何包含通配符的斜杠分隔的模式元素從不參與vendor包路徑中“vendor”元素的匹配,因此./...不匹配./vendor或./mycode/vendor的子目錄中包,但./vendor/...和./mycode/vendor/...可以,然而,注意,自身包含代碼的名字為vendor的目錄不是vendor的包:cmd/vendor可能是名字為vendor的命令,并且模式cmd/...匹配之,更多關于使用vendor的資訊參閱golang.org/s/go15vendor,

匯入路徑也可以命名要從遠程倉庫下載的下載的包,詳細資訊運行“go help importpath”,

程式中的每個包必須有唯一的匯入路徑,按習慣,這通過使每個路徑以屬于你的唯一前綴開始來實作,例如,在Google內部使用的路徑都以“google”開頭,并且表示遠程倉庫的路徑以代碼的路徑開頭,例如“github.com/user/repo”,

程式中的包不必有唯一的包名,但有兩個有特殊含義的保留包名,名字main表示命令,而不是庫,命令會被構建為二進制且不能被匯入,名字documentation表示目錄中非Go程式的檔案,documentation包中的檔案會被go命令忽略,

作為特殊情況,如果包串列是單個目錄中的.go檔案的串列,命令會被應用于恰好由那些檔案構成的單個合成的包,忽略那些檔案中的任何構建約束并忽略目錄中任何其它檔案,

以“.”或“_”開頭的目錄和檔案名會被go工具忽略,如同名字為“testdata”的目錄,

testflag主題——測驗標志

“go test”命令接受應用于“go test”自身的標志和應用于生成的測驗二進制的標志,

標志中的幾個控制性能分析(profiling)并寫入適合“go tool pprof”的性能分析執行的檔案;更多資訊運行“go tool pprof -h”,pprof的--alloc_space、--alloc_objects、--show_bytes選項控制資訊如何呈現,

以下的標志被“go test”命令識別并控制任何測驗的執行:

(譯注:以下標志闡述中,測驗(大多數)指test,基準測驗指benchmark,范例指example;性能分析指profile,)

  • -bench regexp:只運行那些匹配正則運算式的基準測驗,默認情況下,不運行基準測驗,要運行所有基準測驗,使用“-bench .”或“-bench=.”,正則運算式由無括號的斜杠(/)字符分隔為一系列正則運算式,且基準測驗的識別符號的每部分必須匹配序列中對應的元素,如果有的話,匹配項的可能的父項以b.N=1運行來標識子基準測驗,例如,給定-bench=X/Y,頂層基準測驗匹配X且以b.N=1運行來發現任何匹配Y的子基準測驗,其是之后會全部運行的項,

  • -benchtime t:為每個基準測驗運行足夠的迭代以消耗時間t,其被指定為time.Duration(例如,-benchtime 1h30s),默認值為1秒(1s),特殊的語法Nx表示運行基準測驗N次(例如,-benchtime 100x),

  • -count n:運行每個測驗和基準測驗n次(默認為1),如果-cpu被設定,對每個GOMAXPROCS值(譯注:-cpu設定的串列中的每個值)運行n次,范例總是只運行一次,

  • -cover:啟用覆寫率分析,注意因為覆寫率分析通過在編譯前注解源代碼來作業,啟用覆寫率分析的編譯和測驗失敗可能報告和原來的源代碼不對應的行號,

  • -covermode set,count,atomic:設定對被測驗的包的覆寫率分析模式,默認為“set”除非-race被啟用,這種情況下為“atomic”,值為:

    • set(bool):此陳述句是否運行?
    • count(int):此陳述句運行多少次?
    • atomic(int):計數,但在多執行緒測驗中正確;明顯更高消耗,

    會設定-cover,

  • -coverpkg pattern1,pattern2,pattern3:對匹配模式的包的每個測驗應用覆寫率分析,默認對每個測驗只分析被測驗的包,關于包模式的描述參閱“go help packages”,會設定-cover,

  • -cpu 1,2,4:指定GOMAXPROCS(譯注:runtime.GOMAXPROCS的回傳值)值串列,測驗或基準測驗會以此來執行,默認為GOMAXPROCS的當前值,

  • -failfast:在首個測驗失敗之后不再開始新的測驗,

  • -list regexp:列出匹配正則運算式的測驗、基準測驗或范例,沒有測驗、基準測驗或范例會被運行,這只會列出頂層測驗,沒有子測驗或子基準測驗會被展示,

  • -parallel n:允許呼叫t.Parallel的測驗函式并行執行,這個標志的值是同時運行的測驗的最大值;默認下,其設定為GOMAXPROCS的值,注意-parallel只應用于單個測驗二進制中,根據-p標志的設定(參閱“go help build”),“go test”命令也可能為多個包并行運行測驗,

  • -run regexp:只運行匹配正則運算式的那些測驗和范例,對于測驗,正則運算式由無括號的斜杠(/)字符分隔為一系列正則運算式,且測驗的識別符號的每部分必須匹配序列中對應的元素,如果有的話,注意匹配項的可能的父項也會運行,因此-run=X/Y匹配、運行、報告所有匹配X的測驗的的結果,即使它們并沒有匹配Y的子測驗,因為必須運行它們來查找那些子測驗,

  • -short:告訴長時間運行的測驗來縮短它們的運行時間,默認是關閉的,但在all.bash運行期間會設定,因此安裝Go樹可以運行健全的檢查但不會花費時間運行詳盡的測驗,

  • -timeout d:如果測驗二進制運行長于時長d,會panic,如果d是0,超時會被禁用,默認為10分鐘(10m),

  • -v:詳細的輸出:在測驗運行時記錄所有測驗的日志,即使測驗成功也會列印所有由Log和Logf呼叫產生的文本,

  • -vet list:配置“go test”運行期的“go vet”呼叫來使用vet檢查的逗號分隔的串列,如果串列為空,“go test”以一個精心設計的被認為總是值得提及的檢查串列運行“go vet”,如果串列為“off”,“go test”根本不會運行“go vet”,

以下標志也會被“go test”識別并能用來在執行期間對測驗進行性能分析:

  • -benchmem:為基準測驗列印記憶體分配統計資料,
  • -blockprofile block.out:當所有測驗完成時寫入goroutine阻塞性能分析至指定的檔案,會如同-c(譯注:go test的標志)那樣寫入測驗二進制,
  • -blockprofilerate n:通過使用n呼叫runtime.SetBlockProfileRate來控制在goroutine阻塞性能分析中提供的詳細資訊,參閱“go doc runtime.SetBlockProfileRate”,性能分析器旨在程式花費于阻塞平均每n納秒采樣一次阻塞事件,默認情況下,如果-test.blockprofile(譯注:即-blockprofile標志)設定時不帶本標志,所有阻塞事件都會被記錄,等同于-test.blockprofilerate=1,
  • -coverprofile cover.out:在所有測驗通過后寫入覆寫率性能分析至檔案,會設定-cover,
  • -cpuprofile cpu.out:在退出前寫入CPU性能分析至指定的檔案,會如同-c那樣寫入測驗二進制,
  • -memprofile mem.out:在所有測驗通過后寫入記憶體分配性能分析至檔案,會如同-c那樣寫入測驗二進制,
  • -memprofilerate n:通過設定runtime.MemProfileRate啟用更多精確的(并昂貴的)記憶體分配性能分析,參閱“go doc runtime.MemProfileRate”,要對所有記憶體分配進行性能分析,使用-test.memprofilerate=1,
  • -mutexprofile mutex.out:當所有測驗完成時寫入互斥鎖爭用性能分析至指定的檔案,會如同-c那樣寫入測驗二進制,
  • -mutexprofilefraction n:采樣n個持有爭用互斥鎖的goroutine堆疊跟蹤資訊中的1個,
  • -outputdir directory:將性能分析的輸出檔案放置于指定的目錄中,默認為“go test”運行的目錄中,
  • -trace trace.out:在退出前寫入執行跟蹤資訊至指定的檔案,

這些標志的每個也能以可選的“test.”前綴被識別,如同-test.v,然而,當直接呼叫生成的測驗二進制時(“go test -c”的結果),前綴是強制的,

視情況而定,在呼叫測驗二進制之前,“go test”命令重寫或移除在可選的包串列之前和之后的已識別的標志,

例如,命令go test -v -myflag testdata -cpuprofile=prof.out -x將編譯測驗二進制并以pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out運行(-x標志被移除因為其只應用于go命令的執行,而非測驗自身),

生成性能分析的測驗標志(除了用于覆寫率的)也保留測驗二進制在pkg.test中以在分析性能分析結果時使用,

當“go test”運行測驗二進制時,其會在對應的包源代碼目錄內運行,根據測驗的不同,當直接呼叫生成的測驗二進制時可能需要做同樣的事情,

命令列包串列,如果存在,必須出現在任何go test命令不認識的標志之前,繼續上面的例子,包串列本應出現在-myflag之前,但可以出現在-v的任一側,

當“go test”運行在包串列模式時,“go test”快取成功的包測驗結果來避免測驗的不必要重復運行,要禁用測驗快取,使用除可快取標志以外的任意測驗標志或引數,顯式地禁用測驗快取的習慣方式為使用-count=1,

要避免測驗二進制的引數被決議為已知的標志或包名,使用-args(參閱“go help test”),其將命令列中余下部分不決議和不修改地傳遞至測驗二進制,

例如,命令go test -v -args -x -v將編譯測驗二進制并以pkg.test -test.v -x -v運行,類似地,go test -args math將編譯測驗二進制并以pkg.test math運行,

在第一個例子中,-x和第二個-v不修改地傳遞至測驗二進制且對go命令自身沒有影響,在第二個例子中,引數math傳遞至測驗二進制,而不是被決議為包串列,

testfunc主題——測驗函式

“go test”命令期望在與被測驗的包對應的“*_test.go”檔案中找到測驗、基準測驗和范例函式,

測驗函式是一個名為TestXxx(Xxx處不以小寫字母開頭)且應具有特征:

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

基準測驗函式是一個名為BenchmarkXxx且應具有特征:

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

范例函式類似于測驗函式,但取代使用*testing.T來報告成功或失敗,會列印輸出至os.Stdout,如果函式中的最后的注釋以“Output:”開頭,那么輸出精確地與注釋比較(參閱下面的例子),如果最后的注釋以“Unordered output:”開頭,那么輸出與注釋比較,但是忽略行的順序,沒有如此注釋的范例會被編譯但不會被執行,“Output:”后沒有文本的范例會被編譯、執行并期望不產生輸出,

godoc展示ExampleXxx的函式體來示范函式、常量或變數Xxx的使用,接收型別T或*T的方法M的范例命名為ExampleT_M,對給定的函式、常量或變數可能有多個范例,以尾隨的_xxx區分,xxx是不以大寫字母開頭的后綴,

這是范例的例子:

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
}

整個測驗檔案會作為范例展示,當其包含單個范例函式,至少一個其它函式、型別、變數或常量宣告,沒有測驗或基準測驗函式時,

更多資訊參閱testing包的檔案,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/43068.html

標籤:Go

上一篇:記一次golang的記憶體泄露

下一篇:Go語言學習筆記(二)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more