Go中间件必须返回http.Handler或接收http.Handler参数,本质是包装器;顺序应为Recovery→Logging→Auth→RateLimit→Handler;需用context传递数据并完整代理ResponseWriter所有方法。
中间件函数必须返回
或接收
参数
Go 的 HTTP 中间件本质是“包装器”——它不直接处理请求,而是把原始 handler 包一层再返回。常见错误是写成普通函数直接调用
却忘了返回新 handler,导致链路中断。
正确模式:接收一个
,返回另一个
(通常用闭包封装)
错误写法:
—— 没有返回值,无法链式调用
典型签名:
,注意大小写:首字母大写才可导出
如果用
,需显式转换:
中间件顺序错位会导致逻辑失效甚至 panic
中间件执行是栈式(后进先出),注册顺序决定包裹顺序。比如
放在最外层才能捕获内层 panic;而
如果放在日志之后,就可能对未认证请求也记了一条 log。
推荐顺序(由外到内):
反例:
放最里层 → 所有中间件都已执行完毕,认证失去意义
本身不支持中间件链,必须手动组合或借助
类型转换
使用
或
时,
添加的中间件作用于子路由,但根路由仍需单独 wrap
Context 传递值比全局变量或闭包更安全可靠
中间件之间需要共享数据(如用户 ID、请求 ID)时,别用闭包捕获变量或全局 map,容易引发并发读写冲突或上下文污染。
必须用
向 request 注入
取值时务必类型断言并检查是否为 nil:
key 推荐用私有类型(如
),避免字符串 key 冲突
不要往 context 存大量数据或结构体指针——影响 GC 和内存逃逸
ResponseWriter 被包装后必须完整代理所有方法
自定义
(比如用于记录状态码或 body 大小)时,只重写
和
是不够的。标准库某些中间件或 handler 可能调用
、
、
等方法,漏代理会 panic 或静默失败。
go语言参考手册 中文CHM版
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译
下载
立即学习
“
go语言免费学习笔记(深入)
”;
最小安全实现至少要嵌入原
并转发全部方法
用
匿名字段 + 显式方法重写,比全手动列方法更少遗漏
测试要点:触发
(会调
+
)、流式响应(用
)、长连接(
)
第三方库如
的
就依赖完整代理,否则压缩失效
真正难的不是写一个中间件,而是确保它在高并发、多跳路由、异常路径下不丢上下文、不漏方法、不误判状态。这些细节藏在 handler 链的缝隙里,一碰就暴露。
http.Handlerhttp.Handlernext.ServeHTTP()http.Handlerhttp.Handlerfunc logging(next http.Handler) { ... next.ServeHTTP(...) }func Logging(next http.Handler) http.Handlerhttp.HandlerFuncreturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ... })RecoveryAuthRecovery → Logging → Auth → RateLimit → HandlerAuthhttp.ServeMuxhttp.Handlerchigorilla/mux.Use()r = r.WithContext(context.WithValue(r.Context(), key, value))if userID, ok := r.Context().Value(userIDKey).(string); ok { ... }type userIDKey stringResponseWriterWriteHeaderWriteHijackFlushCloseNotifyhttp.ResponseWriterstruct{ http.ResponseWriter }http.RedirectWriteHeaderWriteFlushHijackgo-chi/chi/middlewareCompress