Go语言中如何将Zap Logger作为参数传递给中间件函数链?
实现方案
你可以通过高阶函数+闭包的方式改造中间件,让中间件先接收日志实例,再返回符合Middleware类型定义的函数,完全匹配你期望的调用方式,具体修改步骤如下:
1. 调整中间件函数签名
将原有中间件改造为接收*zap.SugaredLogger参数、返回func(http.Handler) http.Handler类型的高阶函数,返回的函数刚好匹配Middleware数组的元素类型要求,改造后的RequestIdentifier示例如下:
func RequestIdentifier(s *zap.SugaredLogger) func(http.Handler) http.Handler { // 闭包捕获传入的日志实例 return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 此处可直接使用传入的s实例打日志 s.Debug("处理请求标识逻辑") // 原有中间件逻辑不变 next.ServeHTTP(w, r) }) } }
RequestLogger中间件按照完全相同的逻辑改造即可。
2. 调用时直接传入初始化好的日志实例
改造完成后,你的期望写法可以直接正常运行,不需要修改Middleware类型和Apply方法的原有实现:
server := &http.Server{ Addr: addr, Handler: middleware.Middleware{middleware.RequestIdentifier(sugar), middleware.RequestLogger(sugar)}.Apply(router), // ...other fields }
原理解释
- 闭包会持有传入的
sugar日志实例的引用,不需要定义全局变量,符合Zap避免全局Logger的最佳实践 - 改造后
RequestIdentifier(sugar)的返回值类型就是func(http.Handler) http.Handler,完全匹配Middleware数组的元素类型要求,不会出现类型不匹配的编译错误 - Zap的
SugaredLogger本身是并发安全的,所有请求复用同一个日志实例不会有并发问题,性能也符合要求
内容的提问来源于stack exchange,提问作者TheRealFakeNews
相关产品推荐
相关产品推荐

