

新闻资讯
技术学院本文介绍如何在 go 中精准捕获 panic 时的堆栈信息(而非简单重定向 stderr),实现对 panic 输出的结构化获取与定制化处理,避免干扰正常日志流。
Go 默认在发生 panic 时会将所有 goroutine 的堆栈跟踪(stack trace)打印到 os.Stderr 并终止程序。但实际工程中,我们往往需要:
此时,简单重定向 os.Stderr 不仅难以区分 panic 输出与其他日志,还可能破坏并发日志写入的安全性。更可靠的方式是在 panic 发生前主动捕获堆栈——借助 recover() + runtime/debug.Stack()(推荐)或 runtime.Stack()。
✅ 推荐做法:使用 runtime/debug.Stack() 获取当前 goroutine 的 panic 堆栈(简洁、安全、无需参数):
package main
import (
"log"
"runtime/debug"
)
func main() {
defer func() {
if r := recover(); r != nil {
// 捕获 panic 时的堆栈(仅当前 goroutine,格式化好)
stack := debug.Stack()
log.Printf("PANIC CAUGHT: %v\nSTACK:\n%s", r, stack)
// ✅ 此处可进一步:上报 Sentry、写入 ELK、触发 webhook 等
// sendToMonitoring("panic", r, string(stack))
}
}()
panic("something went wrong")
}⚠️ 注意事项:
? 进阶提示:结合 runtime.Caller() 可定位 panic 触发位置;搭配 errors.WithStack(如 github.com/pkg/errors)可增强错误上下文,但注意 debug.Stack() 已包含完整调用链,多数场景无需额外封装。
总结:要精准、干净地获取 panic 输出,请始终优先使用 defer + recover + debug.Stack() 组合。它不侵入标准输出流、不干扰日志系统,且符合 Go 的错误处理哲学——将 panic 视为需显式处理的异常控制流,而非不可控的崩溃事件。