$ GO111MODULE=on go get golang.org/x/tool/cmd/stress
环境变量
1 2 3 4
$ go env $ go env GOPATH GOO GOARCH $ go env -w GOPROXY=https://goproxy.cn,direct $ go help environment
开发
运行代码
1 2 3 4 5 6 7 8 9
$ 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 文档
1 2 3 4 5 6
$ 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
运行测试
1 2 3 4 5 6 7 8 9 10 11
$ 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
1 2 3 4 5 6 7
$ 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
压力测试
1 2 3
$ 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$
$ go vet foo.go # 检查 foo.go 文件 $ go vet . # 检查当前目录下所有文件 $ go vet ./... # 检查当前目录及子目录下所有文件 $ go vet ./foo/bar # 检查 ./foo/bar 目录下所有文件 $ go vet -composites=false ./... # 禁用一些分析器
实验性的分析器
1 2 3 4
$ 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 工具
1
$ go test -vet=off ./...
整理代码(LintingCode)
1 2 3 4 5 6
$ 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
整理和验证依赖
1 2
$ go mod tidy # 移除所有未使用过的依赖 $ go mod verify # 检查依赖的 hash
编译和部署
编译可执行文件
1 2
$ go build -o=/tmp/foo . # 编译当前目录的包 $ go build -o=/tmp/foo ./cmd/foo # 编译 ./cmd/foo 目录的包
编译缓存
1 2 3
$ go env GOCACHE # 检查你的编译缓存存放目录 $ go build -a -o=/tmp/foo . # 强制重编译所有包 $ go clean -cache # 清除缓存
编译过程
1 2
$ go list -deps . | sort -u # 列出用于编译可执行文件的所有包 $ go build -a -x -o=/tmp/foo . # 重建所有内容并显示运行的命令
交叉编译
1 2 3
$ 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
1 2 3 4 5 6 7 8
$ 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"' . # 使二进制文件尽可能静态
问题诊断和优化
运行和比较基准测试
1 2 3 4 5 6 7 8
$ 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运行基准测试
比较基准测试的变化
1 2 3 4 5
$ 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
运行和比较基准测试
1 2 3 4 5 6 7
$ 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 生成
1 2
$ go test -run=^$ -bench=^BenchmarkFoo$ -trace=/tmp/trace.out . $ go tool trace /tmp/trace.out # 目前只在 Chrome/Chromium 可用
$ go list -m -u github.com/alecthomas/chroma # 检查该库是否有新版本 $ go list -m -u all # 更新项目所有依赖
依赖升级或降级
1 2 3
$ 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 # 到特定提交
运行所有包的全部测试检验不兼容性
1
$ go mod tidy $ go test all
使用依赖的本地版本
1 2
$ go mod edit -replace=github.com/alexedwards/argon2id=/home/alex/code/argon2id # 创建 replace 规则 $ go mod edit -dropreplace=github.com/alexedwards/argon2id # 删除 replace 规则