贝利信息

Martini 中全局 panic 恢复中间件的正确实现方式

日期:2026-01-24 00:00 / 作者:碧海醫心

本文详解如何在 martini 框架中正确注册 `recoverwrap` 中间件,实现对所有路由处理器 p

anic 的统一捕获与响应,避免服务崩溃,并指出使用 `martini.context.next()` 的关键原理及注意事项。

Martini 是一个轻量级 Go Web 框架,其中间件机制基于依赖注入与执行链(Context.Next()),并非标准 http.Handler 装饰器模式。因此,直接将 func(http.Handler) http.Handler 类型的函数传给 m.Use() 会导致编译失败——因为 Martini 的 injector 无法解析 http.Handler 作为参数注入。

✅ 正确做法是:编写符合 Martini 中间件签名的函数,接收 martini.Context 和 http.ResponseWriter(或其他可注入类型),并在 defer 中调用 recover(),最后显式调用 c.Next() 触发后续处理器执行:

func RecoverWrap(c martini.Context, w http.ResponseWriter) {
    defer func() {
        if r := recover(); r != nil {
            var err error
            switch v := r.(type) {
            case string:
                err = errors.New(v)
            case error:
                err = v
            default:
                err = errors.New("unknown panic value")
            }
            http.Error(w, "Something goes wrong", http.StatusInternalServerError)
            // 注意:此处不返回,确保响应已写出且链终止
        }
    }()
    c.Next() // 关键:继续执行后续 handler(如路由函数)
}

? 重要注意事项

? 总结:Martini 的中间件本质是“执行链钩子”,依赖 Context.Next() 控制流程,而非 HTTP Handler 套娃。掌握这一模型,才能正确实现日志、鉴权、恢复等通用能力。切勿尝试适配 http.Handler 签名——那是 net/http 或 Gin/Chi 等框架的范式。