使用中间件统一处理Go http错误,通过定义ErrorResponse结构和ErrorMiddlewareAdv函数,结合defer/recover捕获panic,推荐用error返回替代panic,实现错误集中处理。
在 Go 的 HTTP 服务中,统一处理错误是提升代码可维护性和 API 一致性的关键。通过设计中间件捕获路由处理函数中的错误,可以避免在每个 handler 中重复写错误响应逻辑。
使用中间件统一处理错误
Go 的 net/http 本身不提供异常机制,但可以通过中间件包装 handler,利用 defer 和 recover 捕获 panic,同时定义统一的错误响应格式。
核心思路是:创建一个装饰器函数,将普通的
http.HandlerFunc
包装成能自动处理错误的版本。
示例:定义统一错误响应结构
type ErrorResponse struct { Error string `json:"error"` Status int `json:"status"` }
示例:错误处理中间件
func ErrorMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // 捕获 panic defer func() { if err := recover(); err != nil { var errorMsg string var statusCode = http.StatusInternalServerError switch e := err.(type) { case string: errorMsg = e case error: errorMsg = e.Error() default: errorMsg = "internal server error" } log.Printf("Panic: %v", errorMsg) sendErrorResponse(w, statusCode, errorMsg) } }() // 正常执行 handler next(w, r) } } func sendErrorResponse(w http.ResponseWriter, status int, message string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) json.NewEncoder(w).Encode(ErrorResponse{ Error: message, Status: status, }) }
在路由中使用错误中间件
将业务 handler 用中间件包装,即可自动处理错误。
立即学习“go语言免费学习笔记(深入)”;
示例:注册路由
func main() { http.HandleFunc("/user", ErrorMiddleware(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { panic("method not allowed") } // 模拟业务错误 if someCondition { panic("user not found") } fmt.Fprintf(w, `{"data": "ok"}`) })) http.ListenAndServe(":8080", nil) }
主动返回错误而非 panic
虽然 panic 能被 recover 捕获,但更推荐通过返回 error 来控制流程,保持程序稳定性。
改进:使用 error 返回代替 panic
type HttpHandler func(w http.ResponseWriter, r *http.Request) error func ErrorMiddlewareAdv(next HttpHandler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if err := next(w, r); err != nil { log.Printf("Handler error: %v", err) sendErrorResponse(w, http.StatusInternalServerError, err.Error()) } } } // 使用示例 http.HandleFunc("/data", ErrorMiddlewareAdv(func(w http.ResponseWriter, r *http.Request) error { if r.Header.Get("Authorization") == "" { return errors.New("missing auth header") } fmt.Fprintf(w, `{"result": "success"}`) return nil }))
这种方式更清晰,避免滥用 panic,同时仍能统一处理错误。
基本上就这些。中间件 + error 返回 + 统一响应格式,是 Go 中处理 HTTP 错误的简洁可靠方案。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END