go build -gcflags="-s" 是查看 go 汇编的正确方式,需由 go build 自动解析依赖和平台配置;直接 go tool compile -s 会因缺失 import 解析和 goos/goarch 设置而失败或输出失真。

直接用 go tool compile -S 就能看汇编,但必须配对 GOOS/GOARCH、处理好 import 依赖、理解输出不是 GNU 汇编——否则看到的要么是报错,要么是误导性内容。
go tool compile -S 报 “import not found” 怎么办
单文件编译器不解析 import 路径,go tool compile -S main.go 遇到 import "fmt" 就会失败。
- 改用完整构建流程:
go build -gcflags="-S" -o /dev/null main.go,让go build自动解析依赖 - 若项目含
go.mod,确保在模块根目录执行,否则go build可能找不到包 - 临时禁用 import?不行。像
fmt.Println这类调用最终会转成runtime.printint,删掉 import 后函数体可能被内联或优化掉,汇编反而失真
交叉编译时汇编输出平台不匹配
go tool compile -S 默认按当前机器生成汇编(比如 macOS Intel 生成 amd64),但你可能想看 arm64 或 wasm 的指令。
- 必须显式设置环境变量:
GOOS=linux GOARCH=arm64 go build -gcflags="-S" -o /dev/null main.go -
GOOS影响 runtime 符号(如runtime.mstart的入口名),GOARCH决定指令集(ADDQvsadd),漏一个就和目标平台对不上 - wasm 场景要加
GOOS=js GOARCH=wasm,此时输出的是 WebAssembly 文本格式(.wat),不是 Plan 9 汇编
看到的汇编为什么不能用 as/gas 直接汇编
Go 输出的是 Plan 9 风格汇编(MOVQ, ADDQ, SP 偏移写法),GNU 工具链默认不认。
- 这不是 bug,是设计:Go 的
.s是调试/分析用的“伪汇编”,带源码行号、变量帧信息(如"".a+8(SP)),不是为链接器准备的 -
-S输出里出现CALL runtime.printint不代表调 libc,那是 Go 运行时内部函数,地址由链接阶段重定位 - 真要生成可链接的 .s 文件?得手写并用
go tool asm,Go 官方不提供从源码自动生成标准 NASM/GAS 格式的功能
想只看某个函数的汇编但输出太长
-S 没有内置函数过滤参数,全量输出后靠 grep 是唯一实用办法。
- 用
go build -gcflags="-S" main.go 2>&1 | grep -A20 "^"".add$"(注意双引号和点号转义) - 加
-l禁用内联:go build -gcflags="-S -l" main.go,避免add被塞进main导致找不到独立函数块 - 重复
-S(-gcflags="-S -S")会显示 SSA 阶段中间结果,但更难读;日常调优只用一次-S
Plan 9 汇编语法、FP/SP 寄存器约定、runtime 函数命名规则——这些细节不查文档几乎没法准确解读,别指望靠猜。真正卡住的地方往往不是命令怎么敲,而是看到 MOVQ "".~r1+16(FP), AX 时不知道 ~r1 是返回值占位符,+16(FP) 是调用者栈帧偏移。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











