没有go tool ptrace命令,官方工具链中不存在;go tool trace仅记录调度事件,不报死锁,只能在panic前定位阻塞点,如chan send或Mutex等待,真正死锁需依赖panic日志中的goroutine堆栈。

没有 go tool ptrace 这个命令,Go 官方工具链里根本不存在它——你混淆了 go tool trace 和 Linux 的 ptrace 系统调用。
go tool trace 能定位阻塞点,但不报死锁
go tool trace 记录的是 Go 运行时调度事件(goroutine 创建/阻塞/唤醒、GC、系统调用等),不是寄存器或内核态堆栈。它无法检测“所有 goroutine 都睡着了”这种状态,更不会触发或捕获 fatal error: all goroutines are asleep - deadlock! panic。它的价值在于:在程序还没 panic、只是推进缓慢时,帮你看到谁卡在 chan send、谁卡在 sync.runtime_SemacquireMutex、阻塞持续了多久。
- 看到多个 goroutine 长时间停在
chan send→ 检查接收方是否启动、是否走对分支、是否已关闭 channel - 大量 goroutine 停在
sync.(*Mutex).Lock→ 不是死锁,是锁争用;但若只有一个 goroutine 在 running,其余全 waiting,就要怀疑它是否持锁未放 - “Goroutines” 标签页里一堆
Runnable却不执行 → 很可能是GOMAXPROCS太小或 P 不足,不是死锁
死锁发生时,go tool trace 已经失效
一旦 runtime 抛出 fatal error: all goroutines are asleep - deadlock!,进程立即终止,HTTP server 来不及响应任何 /debug/trace 请求。你打开 trace UI 看到的只是 panic 前几秒的空转快照,甚至可能压根没数据——因为 go tool trace 默认只采样启动后前 5 秒,而死锁常发生在第 8 秒、第 12 秒。
- 必须提前启用:
import _ "net/http/pprof"+ 启动http.ListenAndServe("localhost:6060", nil) - 采集命令要显式延长时间:
go tool trace -http=localhost:8080 http://localhost:6060/debug/trace?seconds=30 - 端口被占会导致
ListenAndServe静默失败 → trace 采集不到任何数据,且无提示
真正该看的第一手证据是 panic 日志里的 goroutine 堆栈
运行时 panic 时打印的所有 goroutine 调用栈,不是辅助信息,是唯一可靠的定位依据。别跳过它去翻 pprof 或重跑 trace。
- 重点看
maingoroutine 卡在哪:是ch <- v?<-ch?wg.Wait()?还是mu.Lock()? - 检查其他 goroutine 是否全卡在同一类操作上:比如全部停在
runtime.chansend,但没人停在runtime.chanrecv→ 发送方没人收 - 有没有 goroutine 卡在
select {}或空for {}?那是逻辑遗漏退出条件,也会触发死锁 - 日志被截断时,加
GODEBUG=schedtrace=1000运行,每秒输出调度快照,观察goroutines:数字是否长期为 0
pprof/goroutine 是比 trace 更快的初筛手段
当程序“不动了”但还没 panic,说明还有 goroutine 在 running 或 runnable,这时 curl 'http://localhost:6060/debug/pprof/goroutine?debug=2' 比开 trace UI 更快得到静态快照。
- 搜索关键词:
chan receive、chan send、semacquire、runtime_SemacquireMutex、sync.(*Mutex).Lock -
/debug/pprof/block不适合查死锁:它统计阻塞耗时长的操作,而死锁可能一秒就爆发 - 注意 init 函数里起的 goroutine:如果依赖其他包的 init 结果,会永久 blocked,堆栈里看不到 channel 相关线索
最常被忽略的一点:go tool trace 本身有可观性能开销,缓冲区为 0 的 channel 最容易暴露阻塞点;而带缓冲的 channel 卡住,可能是“暂时满/空”,得结合 len(ch) 和 cap(ch) 判断是否真卡死——不能只看状态。


















