我无法理解 go-kit 中间件,因此我为 Retail_total api 端点设置了一个日志记录中间件。
func MakeTotalRetailPriceHttpHandler(logger log.Logger, svc PricingService) *httptransport.Server {
var retailEndpoint endpoint.Endpoint
retailEndpoint = MakeTotalRetailPriceEndpoint(svc)
retailEndpoint = LogTotalRetailPriceEndpoint(log.With(logger, "service", "PricingService"))(retailEndpoint)
return httptransport.NewServer(
retailEndpoint,
decodeTotalRetailPriceRequest,
encodeResponse,
)
}
这是 logTotalRetailEndpoint 中间件
func LogTotalRetailPriceEndpoint(logger log.Logger) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
logger.Log("endpoint", "TotalRetailPriceEndpoint", "msg", "Calling endpoint")
defer logger.Log("endpoint", "TotalRetailPriceEndpoint", "msg", "Called endpoint")
// diagnostic functionality
return next(ctx, request)
}
}
}
现在我的疑问是日志记录中间件包含带有上下文和请求等参数的函数,这些参数由 next 使用。它们如何传递到中间件?
retailEndpoint(ctx, req) 最终一定会被调用。中间件中使用了相同的 ctx 和 req。 之所以会发生这种情况,是因为当我们执行 LogTotalRetailPriceEndpoint(log.With(logger, "service", "PricingService")) 时,这只是返回一个端点类型的函数。中间件,而不是实际执行端点.中间件类型的函数。当我们返回一个端点.中间件类型的函数后,它需要一个端点.端点类型的函数作为每个签名,所以我们直接将retailEndpoint传递给它。
retailEndpoint = LogTotalRetailPriceEndpoint(log.With(logger, "service", "PricingService"))(retailEndpoint)
最终返回类型为 func(ctx context.Context, request interface{}) 的函数。请注意,此处仅使用 func 分配 RetailEndpoint。我们最里面的函数还没有执行,只有当我们执行retailEndpoint(ctx, req)时才会执行。最里面的函数可以访问 logger 和 next 也是因为闭包(外部作用域变量可以通过闭包中的内部作用域访问。