最安全方式是alice.New(mw1,mw2,mw3).Then(handler),中间件必须为func(http.Handler) http.Handler签名,顺序与执行一致;不可直接嵌套或传给router.GET,需用router.Handler()适配。
直接用
串起中间件,再调用
绑定最终 handler——这是最安全、最符合 Go 标准库语义的组合方式。别手写嵌套,也别试图魔改
接口。
为什么不能直接嵌套 middleware 调用?
像
这种写法看似直白,但实际会带来三个硬伤:
顺序反直觉:最外层中间件最先执行,但写在最左边,阅读时要从右往左理解
难以复用:每次增删中间件都要重写整条链,无法拆分或共享子链
调试困难:panic 堆栈里看不到中间件名,只有匿名函数地址
而
的执行顺序和书写顺序完全一致,新增一个中间件只需往参数列表里加一项。
接收的中间件必须是
这是 Alice 的硬性契约,不是建议。任何不满足该签名的函数都会编译失败:
立即学习
“
go语言免费学习笔记(深入)
”;
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数组安全、编译
下载
❌ 错误示例:
(这是 handler 函数,不是中间件构造器)
❌ 错误示例:
(缺少
参数,无法形成链)
✅ 正确写法:
如果你手头有类似
的老代码,必须包一层适配器,比如:
和 httprouter 等非标准路由器一起用时,别传给
httprouter 的
要求类型是
,而
返回的是
,直接传会报错:
。
✅ 正确做法:用
✅ 或者更推荐:把 alice 链套在标准
或
外层,让 httprouter 只管路由分发,中间件统一由 Alice 管理
⚠️ 注意:
是
的语法糖,返回值类型一样,不能解决类型不匹配问题
Chain 不可变,但
和
会创建新实例
很多人误以为
是原地修改,其实它返回的是一个全新的
。原始变量仍指向旧链:
这种设计避免了意外共享状态,但也意味着你不能靠“追加”来动态改全局链——所有链组合操作都应在初始化阶段完成,运行时只应调用
。
最容易被忽略的一点是:中间件内部如果依赖闭包捕获的变量(比如配置、DB 连接),务必确认这些变量在
调用时已就绪;因为
才真正触发中间件构造函数执行,但构造函数本身是在
时就被存入切片的。
alice.New()Then()http.Handlermw1(mw2(mw3(handler)))alice.New(mw1, mw2, mw3).Then(handler)alice.New()func(http.Handler) http.Handlerfunc(w http.ResponseWriter, r *http.Request)func() http.Handlernextfunc(next http.Handler) http.Handler { return http.HandlerFunc(...) }loggingMiddleware(http.ResponseWriter, *http.Request)func adapt(fn func(http.ResponseWriter, *http.Request)) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fn(w, r)
next.ServeHTTP(w, r)
})
}
}router.GETrouter.GEThttprouter.Handlealice.Chain.Then()http.Handlercannot use ... as type httprouter.Handlerouter.Handler("GET", "/path", chain.Then(handler))http.ServeMuxhttp.HandlerThenFunc()Then()Append()Extend()chain.Append(mw)alice.Chainbase := alice.New(logMW, authMW)
apiChain := base.Append(rateLimitMW) // 新链
webChain := base.Append(compressMW) // 另一个新链,和 apiChain 无关Then()New()Then()New()