Go: toolchain
1 · Go 工具链#
go 命令可以使用内置工具链,也可以使用PATH中的其他版本(按需下载)
通过如下控制:
go.mod或go.work中的go或toolchain指令GOTOOLCHAIN环境变量:默认auto,按go/toolchain选择;local始终内置;go1.21.0固定某个版本;go1.21.3+auto默认但允许按模块要求升级
| 配置项 | 作用 |
|---|---|
go | 模块/工作区最低版本 |
toolchain | 建议使用的工具链版本 |
GOTOOLCHAIN | 强制指定使用的工具链版本 |
1.1 · go version#
作用:查看 Go 二进制文件的构建信息
go help version
go doc runtime/debug.BuildInfo
- 查看当前Go版本:
go version - 指定二进制,查看构建信息:
go version -m <file>
参数:
-m: 模块/依赖/构建信息-json: 配合-m使用,输出json
1.2 · go get#
go get 用于管理模块依赖
go help get
# 1. 添加依赖或升级到最新
go get example.com/pkg
# 2.指定版本
go get example.com/pkg@v1.2.3
# 3.移除依赖
go get example.com/mod@none
# -u 升级到可用的较新 minor/patch 版本
# -u=patch 只升级到可用的较新 patch 版本
# -x 打印执行的命令,方便调试
1.3 · go list#
列出指定包或模块的信息
go help list
# 1. 列出包导入路径
go list
# 2. 列出模块
go list -m
# 3. 列出当前包及其所有递归依赖
go list -deps
# 3. 列出主模块及所有依赖模块
go list -m all
# 4. 列出模块并显示可升级版本
go list -m -u all
# -f format:用 text/template 控制输出
# 只看直接依赖
go list -m -f '{{if not .Indirect}}{{.Path}}{{end}}' all
# 只看间接依赖
go list -m -f '{{if .Indirect}}{{.Path}}{{end}}' all
# 带标记输出
go list -m -f '{{.Path}}{{if .Indirect}} (indirect){{end}}' all
1.4 · go build#
编译指定包及其依赖
# -o 指定输出文件或目录
# -a 强制重新编译,忽略缓存
# -asmflags、-gcflags、-ldflags 闯入底层asm/compile/link工具的参数
# -n 只打印将要执行的命令,不实际执行(dry run)
# -x 打印将要执行的命令,并正常执行
# -tags 构建标签(build tags)
// src/cmd/go/internal/work/build.go:29
// src/cmd/go/internal/work/build.go:461
1.5 · go doc#
查看 Go 包、类型、函数、方法等的文档注释
go doc <pkg> # 包文档
go doc <sym> # 当前包中的符号
go doc <pkg>.<sym> # 指定包中的符号
go doc <pkg>.<sym>.<method> # 指定类型的方法
go doc <pkg> <sym> # 包路径 + 符号
# -all 显示包中全部文档
# -short 每个符号只显示一行摘要
# -u 同时显示未导出符号
# -c 符号匹配时区分大小写
1.6 · go install#
编译并安装指定包
go install [build flags] [packages]
- 带版本:
go install pkg@version按指定版本独立安装 main 包(目标go.mod不能有replace/exclude歧义),忽略当前项目 go.mod,适合安装工具。 - 不带版本:
go install pkg/go install ./cmd/x在当前 module/GOPATH 上下文里解析并安装,能否成功取决于当前上下文是否能解析该包。
1.7 · 编译工具与使用示例
1.7.1 · 工具链概览
| 工具 | 功能 | 阶段 |
|---|---|---|
go tool compile | 编译源文件为目标文件 (.o/.a) | 前端+中端 |
go tool asm | 汇编器,编译汇编代码 | 后端 |
go tool link | 链接器,链接目标文件为可执行文件 | 后端 |
go tool objdump | 反汇编工具,查看二进制内容 | 分析 |
go tool nm | 符号列表工具 | 分析 |
go tool cgo | C 语言互操作 | 特殊 |
go build | 高级构建工具(自动调度) | 完整流程 |
1.7.2 · 示例:编译一个简单的 Go 程序#
创建测试文件 main.go:
package main
import "fmt"
func add(a, b int) int {
return a + b
}
func main() {
result := add(2, 3)
fmt.Println(result)
}
1.7.2.1 · 1. 查看汇编代码#
# 编译时打印汇编(使用 go build)
go build -gcflags=-S main.go 2>&1 | head -100
# 或者使用 go tool compile 直接查看
go tool compile -S main.go 2>&1 | grep -A 20 "func main"
1.7.2.2 · 2. 查看 SSA 优化过程#
# 生成包含所有 SSA 优化阶段的 HTML 文档
GOSSAFUNC=main go tool compile main.go
# 会生成 ssa.html,用浏览器打开查看每个阶段的优化
# 只查看特定函数
GOSSAFUNC=add go tool compile main.go
1.7.2.3 · 3. 查看编译命令(不执行)#
# 打印编译命令但不执行
go build -n main.go
# 输出会显示调用了哪些 compile 和 link 命令
# 打印命令并执行,看完整过程
go build -x main.go
1.7.2.4 · 4. 编译细节控制#
# 禁用优化
go build -gcflags=-N main.go
# 禁用内联
go build -gcflags=-l main.go
# 打印优化决策
go build -gcflags=-m main.go
# 输出会显示内联、逃逸分析等优化信息
# 打印更详细的优化信息
go build -gcflags="-m=2" main.go
# 打印类型检查过程
go build -gcflags=-w main.go
1.7.2.5 · 5. 分析编译后的二进制#
# 查看目标文件中的所有符号
go tool nm main >symbols.txt
# 查看特定符号的大小
go tool nm -size main | grep add
# 反汇编二进制,查看 main 函数的机器码
go tool objdump main | grep -A 30 "TEXT main.main"
# 查看完整的反汇编
go tool objdump main >disasm.txt
1.7.2.6 · 6. 低级编译(手动调用编译器)#
# 只编译当前包,不链接
go tool compile -o main.o main.go
# 打包为归档文件(.a),供后续链接使用
go tool compile -pack -o main.a main.go
对普通 Go 程序,通常应优先使用
go build。go tool compile/go tool link属于底层工具,直接链接可执行文件时还需要处理导入配置、运行时和标准库依赖,不能简单理解为compile + link两步就能替代go build。
1.7.2.7 · 7. 分析构建过程#
# 打印详细的编译过程
go build -v main.go
# 保存临时文件(通常会删除)
go build -work main.go
# 会在最后打印临时目录路径
# 查看导入配置
go build -x main.go 2>&1 | grep importcfg
1.7.3 · 实际用途示例
想要优化程序性能:
# 1. 查看哪些函数被内联
go build -gcflags="-m=2" myapp.go 2>&1 | grep "inlined"
# 2. 查看逃逸分析结果
go build -gcflags="-m=2" myapp.go 2>&1 | grep "escape"
# 3. 查看生成的汇编
go build -gcflags=-S myapp.go >asm.txt
# 4. 关键函数的 SSA 优化过程
GOSSAFUNC=criticalFunc go tool compile myapp.go
想要减小二进制大小:
# 1. 移除 DWARF 调试信息
go build -ldflags="-w" main.go
# 2. 移除符号表
go build -ldflags="-s" main.go
# 3. 同时移除
go build -ldflags="-s -w" main.go
# 4. 查看符号占用空间
go tool nm -S main | sort -k2 -rn | head -20
调试编译问题:
# 1. 打印完整的编译命令
go build -x main.go
# 2. 保存临时编译中间结果
TMPDIR=/tmp/gobuild go build -work main.go
# 3. 检查类型检查过程
go tool compile -d help # 查看所有调试选项
# 4. 竞态检测编译
go build -race main.go