SuperAPI AI 工具集

go-troubleshooting

测试与质量

查看项目

更新于 10-15 21:37

技能介绍

用途:诊断 Go 程序的运行时故障,强调“先诊断后修复”——先复现、观察、定位,再改代码,避免只压住症状导致 bug 转移。

主要能力:按症状选择流程。崩溃带堆栈时读 panic;程序挂起或请求停滞时转储 goroutine 找阻塞点;出现 fatal error: all goroutines are asleep 说明 Go 检测到完全死锁;内存持续增长至 OOM 时做堆 profile 差分;goroutine 数量增长时做 goroutine profile 差分;数据间歇性异常时用竞态检测器;需要交互式查看状态时用 Delve。

读 panic:首行判断 panic 类型,如 nil pointer dereference 且 addr=0x0 表示 nil 接收者、nil 字段或 nil map/指针参数;定位自己代码中最顶层的帧;帧中接收者值如 (*UserService).Notify(0x0, ...) 的 0x0 即接收者为 nil,需回溯其构造位置;非 goroutine 1 时查谁创建了它以及是否应有 recover 边界。

挂起与死锁:用 kill -QUIT <pid> 转储全部 goroutine 栈,或已挂载 net/http/pprof 时用 curl 'localhost:6060/debug/pprof/goroutine?debug=2'。按栈分类:sync.(*Mutex).Lock 上的 [semacquire] 需找持锁者,两把锁互相持有即锁序反转;[chan send]/[chan receive] 说明对端已消失;[select] 缺少 ctx.Done() 分支说明阻塞调用忽略取消;大量相同栈是泄漏而非死锁。

内存泄漏:在长驻服务挂载 pprof(仅私有端口,绝不公开),用 import _ "net/http/pprof" 并监听 localhost:6060。间隔采集堆 profile 后执行 go tool pprof -base heap1.pb.gz heap2.pb.gz,用 top 看最大正增量、list FuncName 定位。常见原因:无淘汰的无界缓存/map、子切片钉住大数组、未停止的 time.Ticker、未关闭的响应体、持续增长的全局切片、遗忘的 goroutine 持有缓冲。

goroutine 泄漏:同样用 -base 差分 goroutine profile,增长栈即泄漏点,修复终止路径(context、channel 关闭);测试中可用 goleak 让遗留 goroutine 的测试失败。

竞态检测:go test -race ./... 与 go build -race ./cmd/api。报告给出写与并发读/写的两个栈及创建位置;修复不是加 sleep,而是加锁保护状态、用 channel 转移所有权或改为不可变。注意 -race 只报告实际执行到的竞态,干净运行不能证明未测路径无问题。

Delve:dlv test ./internal/service -- -test.run TestTransfer 调试测试,dlv attach <pid> 附加进程,dlv core ./api core.1234 事后分析;可用 break、continue、print、goroutines -t、goroutine 43 bt。需要真实值或 goroutine 状态时用它,快速定位时 t.Logf 或 slog.Debug 加一次测试往往更快。

诊断环境变量:GOTRACEBACK=all 让 panic 转储全部 goroutine;GODEBUG=gctrace=1 观察 GC 周期;GOMEMLIMIT=512MiB 设软内存上限,在找真正泄漏期间缓解 OOM。

限制与核对:改动前须已复现症状或取得转储/profile;能解释根因;panic 修复针对 nil/越界来源而非包一层 recover;死锁修复建立单一锁序或去掉共享锁;泄漏修复后 profile 应持平;并发修复后 go test -race ./... 通过;应有回归测试在无修复时失败;pprof 端点只绑定 localhost 或私有接口。资料未提供具体版本、平台与收费信息。