package middleware import ( "log" "net/http" "runtime/debug" "github.com/gin-gonic/gin" "github.com/google/uuid" ) // Recovery 捕获 panic 并返回 500,记录堆栈日志。 // 返回 JSON {"error":"internal_error","request_id":""}。 // request_id 使用 uuid.New() 生成(Recovery 在 RequestID 之前注册, // panic 发生时上下文中可能尚无 request_id,故独立生成)。 func Recovery() gin.HandlerFunc { return func(c *gin.Context) { defer func() { if r := recover(); r != nil { stack := debug.Stack() requestID := uuid.New().String() log.Printf("[recovery] panic recovered, request_id=%s: %v\n%s", requestID, r, stack) // 若已写入部分响应,AbortWithStatusJSON 仍会设置状态并尝试写 JSON c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ "error": "internal_error", "request_id": requestID, }) } }() c.Next() } }