Go中间件链需函数式组合、固定签名func(http.Handler) http.Handler,遵循洋葱模型,用context安全传值,各中间件须独立recover panic。

Go语言构建高扩展性的中间件处理链,关键不在堆砌功能,而在于设计清晰的封装边界、可控的执行顺序和安全的数据传递机制。它不是靠框架自动注册,而是靠函数式组合显式构造,天然支持横向拆分与按需复用。
中间件必须返回http.Handler,不能是普通函数
每个中间件本质是一个“包装器”:接收一个http.Handler,返回一个新的http.Handler。签名固定为:
func(http.Handler) http.Handler- 内部用
http.HandlerFunc转成可调用的闭包 - 若写成
func(http.ResponseWriter, *http.Request)或无返回值,中间件根本不会生效
链的顺序决定逻辑流向,外层最先响应请求
中间件链遵循“洋葱模型”:请求由外向内穿透,响应由内向外返回。例如:
-
logging → auth → rateLimit → handler表示日志最先记录进入,最后记录退出 - 鉴权失败时,在
auth中不调用next.ServeHTTP,直接写401并返回,链即终止 - 限流中间件可在调用
next前检查配额,也可在之后统计实际耗用
用context安全传递数据,避免修改原始*Request
中间件之间需要共享信息(如用户ID、请求ID、解析后的token),但*http.Request是不可变的。正确做法是:
立即学习“go语言免费学习笔记(深入)”;
- 调用
r.WithContext(ctx)创建新请求对象 - 将结构体或键值对存入
context.WithValue - 下游中间件或业务处理器通过
r.Context().Value(key)读取 - 避免用全局变量或闭包捕获外部状态,否则并发下易出错
panic必须兜底,否则整个服务会崩溃
Go的http.Server默认不recover panic。一个中间件里空指针或JSON解析失败,会导致整个HTTP服务中断:
- 所有中间件最外层应包裹
defer func(){ if r := recover(); r != nil { /* 记录错误,返回500 */ } }() - 尤其在解析body、解密token、调用第三方API等易错环节前加recover
- 不要依赖上层中间件来recover,每个中间件应具备独立容错能力


















