必须用 dlv test 启动测试调试会话,而非普通 go test;需在含 go.mod 的包根目录执行,加 -gcflags="-l -n" 确保变量可见,断点须用完整包路径如 myproj/pkg.testfoo。

用 dlv test 启动测试调试会话
Delve 本身不支持在普通 go test 运行时动态附加,必须用 dlv test 替代原命令启动——这是最常卡住的第一步。它会编译测试二进制并立即进入调试器,等你下断点后再执行。
常见错误现象:could not launch process: fork/exec /tmp/go-build...: no such file or directory,通常因为当前目录没 go.mod 或不在 GOPATH/src 下,Delve 找不到可构建的包。
- 确保在待测包根目录(含
go.mod或main.go同级)执行 - 调试单个测试函数:加
-test.run ^TestFoo$(注意正则边界,避免匹配到TestFoobar) - 想跳过测试 setup 阶段直接停在测试函数入口?用
dlv test -test.run ^TestFoo$ --headless --api-version=2+dlv connect更可控
在测试函数里设断点要写对函数签名
Go 测试函数是编译后被包装过的,TestXxx 不是顶层符号名。Delve 查不到 TestFoo 就报 location not found,不是路径错,是函数名没识别对。
正确做法:先 dlv test -test.run ^TestFoo$ 启动,进 dlv 后用 funcs TestFoo 列出匹配函数,通常看到类似 myproj/pkg.TestFoo 或 myproj/pkg.TestFoo-fm(后者是闭包包装版)。
- 断点设成
b myproj/pkg.TestFoo,别漏包路径 - 如果测试里用了
t.Run("sub", func(t *testing.T) {...}),子测试函数无法直接断点,得在子测试体内部行号下断(如b pkg/file.go:42) - 用
bp查看已设断点,确认状态是enabled而非pending(pending 表示符号未加载,常因未运行到该包)
调试时变量不可见或显示 <autogenerated></autogenerated>
Delve 默认不加载 Go 的调试信息(debug_line 等),尤其在启用 -gcflags="-l"(禁用内联)前,局部变量、参数可能显示为 <autogenerated></autogenerated> 或完全丢失。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
这不是 Delve bug,是 Go 编译器优化导致调试信息缺失。不关掉优化,断点进了也白进。
- 务必加编译参数:
dlv test -gcflags="-l -N" -test.run ^TestFoo$ -
-l禁用内联(让函数调用栈清晰),-N禁用变量寄存器优化(让print v能看到值) - 这两个 flag 会让二进制变大、运行稍慢,但调试阶段值得——生产环境当然要开优化,但调试时不加它们,等于蒙眼修车
用 continue 和 next 控制测试流程别踩坑
测试函数里有 t.Fatal、t.Skip 或并发 goroutine 时,next 可能跳进标准库甚至 runtime,不是你的代码;而 continue 会直接跑完当前测试,错过中间状态。
真实调试场景中,你往往只想“单步过自己的逻辑,跳过标准库”,但 Delve 没有 Go 专属的“step over stdlib”指令。
- 用
step(s)进函数,next(n)过当前行——但遇到t.Log时它会进testing包,此时按finish(f)更快退回来 - 想观察某个表达式变化?用
print someVar或简写p someVar,比反复next看变量窗口更直接 - 测试 panic 了?Delve 默认不停,需提前
trace sync.runtime_Semacquire或更实际的做法:加-dwarf-location并用on panic设置条件断点(较重,一般先用dlv test -test.paniconexit=1让 panic 触发 exit 再 attach)
最易被忽略的是:Delve 的 test 子命令不会自动读取项目根目录下的 .dlv/config.yml,所有调试行为都依赖启动时参数。写好脚本封装 dlv test -gcflags="-l -N" -test.run 是长期省事的关键。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










