GoLand 不提供死锁检测功能,需通过运行时 panic、调试器查看 goroutine 状态、pprof 抓取堆栈等方式定位;死锁是逻辑错误,必须实际运行程序才能暴露。

GoLand 本身不提供死锁检测功能
GoLand 是 JetBrains 的 Go IDE,它依赖 Go 工具链做底层分析,而 Go 官方 runtime 仅在程序运行时(且仅限 go run 或 go test)通过 -race 检测数据竞争,**不检测死锁**。死锁是逻辑错误,Go 运行时会在所有 goroutine 都阻塞时 panic 并打印堆栈,但这个行为不会被 GoLand 自动捕获或高亮——你得自己触发它。
所以别指望在编辑器里点几下就“发现死锁”,关键动作发生在运行阶段。
用 go run -gcflags="-l" main.go 配合调试器观察 goroutine 状态
GoLand 调试器能显示所有 goroutine 的当前状态(running、waiting、syscall 等),这是定位死锁最直接的手段。前提是代码已启动并卡住。
GoLand 2026.1.1 是 2026.1 发布后的首个维护修正版本,适合已经开始体验 2026.1 新功能并希望同步补丁的开发者。它更适合用于入门项目、现有项目迁移测试和 IDE 行为验证。
- 在疑似死锁位置(比如 channel receive、
sync.Mutex.Lock()、sync.WaitGroup.Wait())设断点 - 以 Debug 模式运行(不是 Run),等程序卡住后,在 Debug 工具窗口 → Goroutines 标签页查看每个 goroutine 的调用栈和状态
- 重点关注状态为
waiting且停在 channel 操作、锁、或select{}的 goroutine;如果多个 goroutine 互相等待(如 A 等 B 发送,B 等 A 发送),就是典型死锁 -
-gcflags="-l"关闭内联,能让断点更准、堆栈更清晰,尤其对小函数有用
手动触发死锁 panic 并读取 fatal error: all goroutines are asleep - deadlock!
Go 运行时只要检测到所有 goroutine 都阻塞且无法唤醒,就会 panic 并输出这句错误。这不是警告,是终止信号,必须让程序实际跑起来才能看到。
- 确保你的 main 函数或测试最终会退出(比如没加
time.Sleep(10 * time.Second)假装“还在运行”) - 删掉所有
log.Fatal或os.Exit以外的提前退出逻辑,否则可能根本走不到死锁点 - 在 GoLand 中右键 → Run 'go run main.go',而不是 Debug;一旦出现
fatal error: all goroutines are asleep - deadlock!,立刻看控制台输出的 goroutine 堆栈 —— 最上面几个 goroutine 就是死锁参与者 - 注意:如果用了
select {}空 select,它会让 goroutine 永久阻塞,但不会触发死锁 panic(除非它是唯一 goroutine)
用 pprof 查 goroutine dump 辅助分析
当死锁发生在复杂服务中(比如 HTTP server 启动后才卡住),手动等 panic 不现实。这时可借助 pprof 抓实时 goroutine 快照。
- 在代码里加
import _ "net/http/pprof",并在某处启动http.ListenAndServe("localhost:6060", nil) - 运行程序后,在终端执行
go tool pprof http://localhost:6060/debug/pprof/goroutine?debug=2 - GoLand 不能直接打开 pprof 结果,但你可以把输出保存成文本,搜索
chan receive、semacquire、sync.(*Mutex).Lock等关键词,快速定位阻塞点 - 注意:goroutine dump 不会告诉你“为什么卡”,只告诉你“卡在哪”,需结合代码逻辑反推依赖关系
死锁没有银弹工具,核心在于理解 channel 发送/接收的配对、锁的持有顺序、WaitGroup 的 Add/Done 是否匹配——IDE 只是帮你看到 goroutine 状态的窗口,真正推理还得靠人。

















