golangpanic信息捕获
- 软件开发
- 2025-08-28 01:54:01

背景
我们的日志接入阿里云sls平台,但是,日志是以json的格式存储在阿里云sls平台上,程序中产生的error,info等日志都可以实现以json的格式打印。但是,golang程序中产生的panic信息本身不是以json的格式输出,这就导致panic信息在阿里云sls平台上不方便检索。
基于上述痛点,我们期望捕获程序的panic信息,并且以json的格式打印,如此,我们就可以方便的实现在阿里云sls平台上检索的目的。
解决方案 核心的思路通过defer和recover()机制捕获panic信息,结合Go的JSON序列化能力,将堆栈信息、错误内容等关键数据封装为结构化JSON格式。
实现步骤 定义日志的结构体日志结构体定义:
type PanicLog struct { Timestamp string `json:"@timestamp"` Level string `json:"level"` Message string `json:"message"` Stack string `json:"stack"` Service string `json:"service"` } 封装打印日志的方法 func logPanicAsJSON(panicObj interface{}) { stack := string(debug.Stack()) // 获取完整堆栈 logEntry := PanicLog{ Timestamp: time.Now().Format(time.RFC3339), Level: "PANIC", Message: fmt.Sprintf("%v", panicObj), Stack: stack, Service: "your-service-name", } jsonData, _ := json.Marshal(logEntry) // 输出到SLS(根据实际日志库选择方式) log.Println(string(jsonData) ) } 封装方法捕获panic defer func() { if r := recover(); r != nil { logPanicAsJSON(r) // 记录 panic 信息 c.AbortWithStatus(http.StatusInternalServerError) } }() 测试案例 package main import ( "encoding/json" "fmt" "log" "os" "runtime/debug" "time" ) type PanicLog struct { Timestamp string `json:"@timestamp"` Level string `json:"level"` Message string `json:"message"` Stack string `json:"stack"` Service string `json:"service"` } func main() { defer func() { if r := recover(); r != nil { // 捕获panic信息并转换为JSON logPanicAsJSON(r) os.Exit(1) } }() // 业务代码... testPanic() time.Sleep(1 * time.Second) } func testPanic() { // nil指针引发panic var a *int *a = 1 } func logPanicAsJSON(panicObj interface{}) { stack := string(debug.Stack()) // 获取完整堆栈 logEntry := PanicLog{ Timestamp: time.Now().Format(time.RFC3339), Level: "PANIC", Message: fmt.Sprintf("%v", panicObj), Stack: stack, Service: "your-service-name", } jsonData, _ := json.Marshal(logEntry) // 输出到SLS(根据实际日志库选择方式) log.Println(string(jsonData)) } 注意事项在Go语言里,recover() 函数只能捕获当前goroutine内产生的 panic。
所以,在下面的这个案例中recover不能捕获到panic信息。如果需要捕获到,需要在每个协程中都执行recover的逻辑。
func main() { defer func() { if r := recover(); r != nil { // 捕获panic信息并转换为JSON logPanicAsJSON(r) os.Exit(1) } }() // 业务代码... go func() { testPanic() }() time.Sleep(1 * time.Second) } 扩展优化日志结构体中增加traceId信息维度。
golangpanic信息捕获由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“golangpanic信息捕获”