如何将记录器作为参数传递给中间件函数链?
How to pass a logger as an argument to a chain of middleware functions?
我是 Go 新手,所以请多多包涵。
我正在尝试使用 Uber 的 Zap 日志包。我仔细阅读了文档并查看了许多示例,但仍在努力寻找如何最好地使用它。他们的 FAQ 部分说要避免将 Zap 用作全局记录器,所以我试图将 server.go
(紧接在下面)中初始化的内容传递给其他函数。
// Initialize logger
logger, err := zap.NewProduction()
if err != nil {
log.Fatalf("Failed to initialize zap logger: %v", err)
}
defer logger.Sync()
sugar := logger.Sugar()
sugar.Info("Server is starting...")
router := http.NewServeMux()
server := &http.Server{
Addr: addr,
Handler: middleware.Middleware{middleware.RequestIdentifier, middleware.RequestLogger}.Apply(router),
// ...other fields
}
其中 Middleware
在另一个文件中定义为
type Middleware []func(http.Handler) http.Handler
// Apply() builds the middleware array into a handler chain
func (midware Middleware) Apply(handler http.Handler) http.Handler {
if len(midware) == 0 {
return handler
}
return midware[:len(midware)-1].Apply(midware[len(midware)-1](handler))
}
然后在另一个文件中(request_identifier.go
)。
func RequestIdentifier(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//
// ...stuff, and use Zap here
//
next.ServeHTTP(w, r)
})
}
其他中间件功能也类似。
我试过包装 RequestIdentifier
并尝试玩弄中间件的公认函数签名,但我似乎无法弄清楚如何在没有我的 [= 的情况下通过 sugar
36=] 对我大吼大叫。
我想要的是:
Handler: middleware.Middleware{middleware.RequestIdentifier(sugar), middleware.RequestLogger(sugar)}.Apply(router)
然后在我的中间件函数中,以某种方式访问可用的记录器,如下所示:
func RequestIdentifier(next http.Handler, s *zap.SugaredLogger) http.Handler { ... }
您需要再添加一层闭包:
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) {
//
// ...stuff, and use Zap here
//
next.ServeHTTP(w, r)
})
}
}
Handler: middleware.Middleware{middleware.RequestIdentifier(sugar), middleware.RequestLogger(sugar)}.Apply(router),
我是 Go 新手,所以请多多包涵。
我正在尝试使用 Uber 的 Zap 日志包。我仔细阅读了文档并查看了许多示例,但仍在努力寻找如何最好地使用它。他们的 FAQ 部分说要避免将 Zap 用作全局记录器,所以我试图将 server.go
(紧接在下面)中初始化的内容传递给其他函数。
// Initialize logger
logger, err := zap.NewProduction()
if err != nil {
log.Fatalf("Failed to initialize zap logger: %v", err)
}
defer logger.Sync()
sugar := logger.Sugar()
sugar.Info("Server is starting...")
router := http.NewServeMux()
server := &http.Server{
Addr: addr,
Handler: middleware.Middleware{middleware.RequestIdentifier, middleware.RequestLogger}.Apply(router),
// ...other fields
}
其中 Middleware
在另一个文件中定义为
type Middleware []func(http.Handler) http.Handler
// Apply() builds the middleware array into a handler chain
func (midware Middleware) Apply(handler http.Handler) http.Handler {
if len(midware) == 0 {
return handler
}
return midware[:len(midware)-1].Apply(midware[len(midware)-1](handler))
}
然后在另一个文件中(request_identifier.go
)。
func RequestIdentifier(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//
// ...stuff, and use Zap here
//
next.ServeHTTP(w, r)
})
}
其他中间件功能也类似。
我试过包装 RequestIdentifier
并尝试玩弄中间件的公认函数签名,但我似乎无法弄清楚如何在没有我的 [= 的情况下通过 sugar
36=] 对我大吼大叫。
我想要的是:
Handler: middleware.Middleware{middleware.RequestIdentifier(sugar), middleware.RequestLogger(sugar)}.Apply(router)
然后在我的中间件函数中,以某种方式访问可用的记录器,如下所示:
func RequestIdentifier(next http.Handler, s *zap.SugaredLogger) http.Handler { ... }
您需要再添加一层闭包:
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) {
//
// ...stuff, and use Zap here
//
next.ServeHTTP(w, r)
})
}
}
Handler: middleware.Middleware{middleware.RequestIdentifier(sugar), middleware.RequestLogger(sugar)}.Apply(router),