安裝工具
最簡單的方式
$ go get -u golang.org/x/tool/...
替代方式
$ GO111MODULE=on go get golang.org/x/tool/cmd/stress
環境變量
$ go env
$ go env GOPATH GOO GOARCH
$ go env -w GOPROXY=https://goproxy.cn,direct
$ go help environment
開發
運行代碼
$ go run . # 運行當前目錄的包
$ go run ./cmd/foo # 運行 ./cmd/foo 目錄下的包 獲取依賴
$ go get github.com/foo/bar@v1.2.3
$ go get github.com/foo/bar@8e1b8d3
$ go list -m all # 顯示所有依賴
$ go mod why -m golang.org/x/y # 為什依賴它?
$ go clean -modcache # 清除模塊緩存 格式化代碼
$ gofmt -d -w -r 'foo -> Foo' . # 替換 foo 為 Foo
$ gofmt -d -w -r 'strings.Replace(a, b, -1) -> strings.ReplaceAll(a, b)' .
查看 Go 文檔
$ go doc strings # 查看 strings 包的簡化版文檔
$ go doc -all strings # 查看 strings 包的全部文檔
$ go doc strings.Replace # 查看 strings.Replace 函數的文檔
$ go doc sql.DB # 查看 database/sql.DB 類型的文檔
$ go doc sql.DB.Query # 查看 database/sql.DB.Query 方法的文檔
$ go doc -src strings.Replace # 查看 strings.Replace 函數的源碼
Testing
運行測試
$ go test . # 運行當前目錄的所有測試
$ go test ./... # 運行當前目錄及其子目錄的所有測試
$ go test ./foo/bar # 運行 ./foo/bar 目錄的所有測試
$ go test -race ./... # 啟用 race 檢測的測試
$ go test -count=1 ./... # 運行測試時繞過測試緩存
$ go clean -testcache # 刪除所有緩存的測試結果
$ go test -v -run=^TestFooBar$ . # 運行名稱為 TestFooBar 的測試
$ go test -v -run=^TestFoo . # 運行名稱以 TestFoo 開頭的測試
$ go test -v -run=^TestFooBar$/^Baz$ . # 僅運行 FooBar 測試下的 Baz 子測試
$ go test -short ./... # 跳過長時間運行的測試
$ go test -failfast ./... # 失敗后請勿再進行進一步的測試
Profiling Test Coverage
$ go test -cover ./...
$ go test -coverprofile=/tmp/profile.out ./... # coverage profile for browser
$ go tool cover -html=/tmp/profile.out
$ go test -covermode=count -coverprofile=/tmp/profile.out ./... # coverage with frequency shown
$ go tool cover -html=/tmp/profile.out
$ go test -coverprofile=/tmp/profile.out ./... # coverage in CLI without any browser
$ go tool cover -func=/tmp/profile.out
壓力測試
$ go test -run=^TestFooBar$ -count=500 .
$ go test -c -o=/tmp/foo.test . # 使用壓力工具 golang.org/x/tools/cmd/stress
$ stress -p=4 /tmp/foo.test -test.run=^TestFooBar$
Testing all dependencies
$ go test all
提交前檢查
格式化代碼
$ gofmt -w -s -d foo.go # 格式化 foo.go 文件
$ gofmt -w -s -d . # 遞歸格式化當前目錄和子目錄所有文件
$ go fmt ./... # 另外一種格式化工具,等價 gofmt -l -w ./...
通過 vet 進行靜態分析
$ go vet foo.go # 檢查 foo.go 文件
$ go vet . # 檢查當前目錄下所有文件
$ go vet ./... # 檢查當前目錄及子目錄下所有文件
$ go vet ./foo/bar # 檢查 ./foo/bar 目錄下所有文件
$ go vet -composites=false ./... # 禁用一些分析器
實驗性的分析器
$ cd /tmp
$ GO111MODULE=on go get golang.org/x/tools/go/analysis/passes/nilness/cmd/nilness
$ GO111MODULE=on go get golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
$ go vet -vettool=$(which nilness) ./...
測試時禁用 vet 工具
$ go test -vet=off ./...
整理代碼(LintingCode)
$ cd /tmp # 安裝 linter
$ GO111MODULE=on go get golang.org/x/lint/golint
$ golint foo.go # Lint the foo.go file
$ golint . # Lint all files in the current directory
$ golint ./... # Lint all files in the current directory and sub-directories
$ golint ./foo/bar # Lint all files in the ./foo/bar directory
整理和驗證依賴
$ go mod tidy # 移除所有未使用過的依賴
$ go mod verify # 檢查依賴的 hash
編譯和部署
編譯可執行文件
$ go build -o=/tmp/foo . # 編譯當前目錄的包
$ go build -o=/tmp/foo ./cmd/foo # 編譯 ./cmd/foo 目錄的包
編譯緩存
$ go env GOCACHE # 檢查你的編譯緩存存放目錄
$ go build -a -o=/tmp/foo . # 強制重編譯所有包
$ go clean -cache # 清除緩存
編譯過程
$ go list -deps . | sort -u # 列出用於編譯可執行文件的所有包
$ go build -a -x -o=/tmp/foo . # 重建所有內容並顯示運行的命令
交叉編譯
$ GOOS=linux GOARCH=amd64 go build -o=/tmp/linux_amd64/foo .
$ GOOS=windows GOARCH=amd64 go build -o=/tmp/windows_amd64/foo.exe .
$ go tool dist list # 列出所有支持的操作系統和CPU架構
使用編譯器和鏈接器 flags
$ go tool compile -help # 查看編譯器可用的 flag
$ go build -gcflags="-m -m" -o=/tmp/foo . # 打印有關優化決策的信息
$ go build -gcflags="all=-m" -o=/tmp/foo . # 打印包括依賴的優化決策信息
$ go build -gcflags="all=-N -l" -o=/tmp/foo . # 禁用優化和內聯
$ go tool link -help # 查看鏈接器可用的 flag
$ go build -ldflags="-X main.version=1.2.3" -o=/tmp/foo . # 增加版本信息
$ go build -ldflags="-s -w" -o=/tmp/foo . # 從二進制文件中刪除調試信息
$ CGO_ENABLE=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' . # 使二進制文件盡可能靜態
問題診斷和優化
運行和比較基准測試
$ go test -bench=. ./... # 運行所有測試和基准測試
$ go test -run=^$ -bench=. ./... # 只運行所有的基准測試
$ go test -run=^$ -bench=^BenchmarkFoo$ ./... # 只運行 BenchmarkFoo 基准測試
$ go test -bench=. -benchmem ./... # 強制將內存分配統計信息包含在輸出中
$ go test -bench=. -benchtime=5s ./... # 運行每個基准測試至少5秒鍾
$ go test -bench=. -benchtime=500x ./... # 保證每個基准測試精確進行500次迭代
$ go test -bench=. -count=3 ./... # 重復每個基准測試3次
$ go test -bench=. -cpu=1,4,8 ./.... # 將GOMAXPROCS設置為1、4和8運行基准測試
比較基准測試的變化
$ cd /tmp # 安裝 benchcmp 工具
$ GO111MODULE=on go get golang.org/x/tools/cmd/benchcmp
$ go test -run=^$ -bench=. -benchmem ./... > /tmp/old.txt # 進行一些修改、優化
$ go test -run=^$ -bench=. -benchmem ./... > /tmp/new.txt
$ benchcmp /tmp/old.txt /tmp/new.txt
Profiling and Tracing
運行和比較基准測試
$ go test -run=^$ -bench=^BenchmarkFoo$ -cpuprofile=/tmp/cpuprofile.out .
$ go test -run=^$ -bench=^BenchmarkFoo$ -memprofile=/tmp/memprofile.out .
$ go test -run=^$ -bench=^BenchmarkFoo$ -blockprofile=/tmp/blockprofile.out .
$ go test -run=^$ -bench=^BenchmarkFoo$ -mutexprofile=/tmp/mutexprofile.out .
$ go test -run=^$ -bench=^BenchmarkFoo$ -o=/tmp/foo.test -cpuprofile=/tmp/cpuprofile.out .
$ go tool pprof -http=:5000 /tmp/cpuprofile.out # 在瀏覽器中審查
$ go tool pprof --nodefraction=0.1 -http=:5000 /tmp/cpuprofile.out # 忽略小於 10% 的節點
Tracing 生成
$ go test -run=^$ -bench=^BenchmarkFoo$ -trace=/tmp/trace.out .
$ go tool trace /tmp/trace.out # 目前只在 Chrome/Chromium 可用
競態條件檢查
$ go build -race -o=/tmp/foo . # 別用於生產環境
$ GORACE="log_path=/tmp/race" /tmp/foo # 輸出到文件而不是標准錯誤
依賴管理(Module)
項目依賴更新
$ go list -m -u github.com/alecthomas/chroma # 檢查該庫是否有新版本
$ go list -m -u all # 更新項目所有依賴
依賴升級或降級
$ go get github.com/foo/bar@latest # 最新版本
$ go get github.com/foo/bar@v1.2.3 # 特定版本 v1.2.3
$ go get github.com/foo/bar@7e0369f # 到特定提交
運行所有包的全部測試檢驗不兼容性
$ go mod tidy $ go test all
使用依賴的本地版本
$ go mod edit -replace=github.com/alexedwards/argon2id=/home/alex/code/argon2id # 創建 replace 規則
$ go mod edit -dropreplace=github.com/alexedwards/argon2id # 刪除 replace 規則
其他工具
升級代碼到 Go 新版本
$ go fix ./...
報告 Bug
$ go bug # 會打開瀏覽器,定位 Go 代碼倉庫的 issue 頁面