go debug(ai)
介绍如何在 Go 程序中进行调试。
虽然 Go 语言官方推荐使用 Delve (dlv) 作为调试器,但如果你必须使用 GDB(例如在某些受限环境或习惯原因),以下是详细的步骤。
1. 编译代码(关键步骤)
默认情况下,Go 编译器会进行内联优化和变量寄存器化,这会让 GDB 无法准确断点或查看变量。必须使用 -gcflags "-N -l" 参数来禁用优化和内联。
1
2
# 假设你的入口文件在 cmd/main.go
go build -gcflags "all=-N -l" -o myapp cmd/main.go
-N: 禁用优化。-l: 禁用内联。
2. 启动 GDB
加载编译好的二进制文件:
1
gdb ./myapp
注意:如果在加载时看到 “Dwarf Error”,说明你的 GDB 版本可能太老,不支持 Go 生成的 DWARF 信息。
3. GDB 常用调试命令 (针对 Go)
Go 的函数名在 GDB 中包含包路径。例如 main 包下的 main 函数通常是 main.main。
设置断点
(gdb) break main.main
# 或者在特定文件行号
(gdb) break /path/to/project/cmd/main.go:15
运行程序
(gdb) run
# 如果需要传参
(gdb) run arg1 arg2
查看源码
(gdb) list
单步调试
(gdb) next # 单步执行(不进入函数)
(gdb) step # 单步执行(进入函数)
查看变量
(gdb) print varName
(gdb) info locals
查看 Goroutines (GDB 的弱项)
Go 运行时提供了一个 python 脚本扩展来帮助 GDB 理解 Goroutine。
(gdb) info goroutines
如果没有加载,你可能需要手动 source Go 安装目录下的 src/runtime/runtime-gdb.py。
4. 强烈建议:使用 Delve (dlv)
Delve 是 Go 语言官方推荐的调试器,它对 Go 的运行时(Runtime)、数据结构(Map, Channel, Interface)和并发模型(Goroutines)有原生且完美的支持。
4.1 安装 Delve
1
go install github.com/go-delve/delve/cmd/dlv@latest
安装完成后,确保 $(go env GOPATH)/bin 在你的系统 PATH 中。
4.2 启动调试
Delve 提供了多种启动模式,适应不同场景:
A. 源码调试 (最常用) 直接编译并启动调试,无需手动 go build。
1
2
# 也就是 go run 的调试版
dlv debug ./cmd/main.go -- arg1 arg2
B. 调试测试代码 调试 _test.go 文件。
1
2
# 也就是 go test 的调试版
dlv test ./pkg/somepackage -- -test.v
C. 调试已编译的二进制 如果你已经编译好了(记得加 -gcflags "all=-N -l"),可以直接加载。
1
dlv exec ./bin/caracal-gateway-debug -- arg1 arg2
D. 附加到运行中的进程 调试正在运行的服务(生产环境排查神器)。
1
2
# 需要 root 权限
dlv attach <PID>
4.3 Delve 常用交互命令
启动 dlv 后,你会进入 (dlv) 交互终端。
断点管理 (Breakpoints)
break(或b):设置断点。b main.main:在 main 函数入口断点。b ./cmd/main.go:15:在指定文件行号断点。b pkg/core/http_jwt.go:45:支持相对路径。
breakpoints(或bp):列出所有断点。clear <id>:清除指定 ID 的断点。clearall:清除所有断点。
流程控制 (Execution)
continue(或c):运行直到断点或程序结束。next(或n):单步执行(不进入函数内部)。step(或s):单步执行(进入函数内部)。stepout:执行完当前函数并返回到调用者。restart(或r):重新启动进程。
变量与状态 (Variables & State)
print(或p):打印变量值。支持 Go 表达式。p req.Usernamep len(slice)
locals:打印当前函数栈帧内的所有局部变量。args:打印当前函数的输入参数。vars <regex>:搜索并打印全局变量。whatis <expr>:查看表达式的类型信息。
堆栈与协程 (Stack & Goroutines) —— Delve 的强项
stack(或bt):查看当前协程的调用栈。goroutines:列出所有 Goroutine。goroutines -t:展开显示每个 Goroutine 的栈顶信息。
goroutine <id>:切换到指定的 Goroutine 上下文。- 切换后,再用
stack或locals查看的就是那个协程的状态。
- 切换后,再用
4.4 IDE 集成
- VS Code / GoLand:这些编辑器的图形化调试功能底层调用的就是
dlv。如果你配置了launch.json(VS Code) 或 Run Configuration (GoLand),你实际上正在使用 Delve。 - 配置建议:在 IDE 中调试时,如果遇到变量被优化掉显示不全的情况,请确保使用了
-gcflags "all=-N -l"构建参数(参考本文档第 1 节)。
总结: 如果只是简单的逻辑调试,GDB 配合 -gcflags "-N -l" 可以使用;但如果是涉及并发、复杂数据结构的调试,请务必使用 Delve。