减少多路复用器中间件和自定义上下文实现中的样板

Reducing boilerplate in a mux middlware and custom context implementation

我是 Go 的新手,正在尝试在我在 mux 之上构建的网关库中创建中间件实现。到目前为止,我想出了这个:

type (
    MyContext struct {
        // ...
    }

    APIGateway struct {
        mux *mux.Router
        ctx *MyContext
    }
)

type MiddlewareFunc func(*MyContext) func(http.Handler) http.Handler

func (a APIGateway) Use(mw MiddlewareFunc) {
    a.mux.Use(mw(ctx))
}

这可行,但我必须处理大量样板代码。在此模式上实现的最简单的中间件必须至少有两个 return 语句和大量倾斜函数声明。

func someMiddleware(ctx *MyContext) func(http.Handler) http.Handler {
    return func(handler http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // Application Logic here
            handler.ServeHTTP(w, r)
        })
    }
}

当中间件必须采用一些额外的参数时,这很快就会成为一个更大的问题,因为现在它必须处理三个 return 语句:

func LogginMiddleware(c LoggerConfig) MiddlewareFunc {
    return func(ctx *MyContext) func(http.Handler) http.Handler {
        return func(handler http.Handler) http.Handler {
            return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                // ...
                handler.ServeHTTP(w, r)
                // ...
            })
        }
    }
}

有什么方法可以减少样板代码的参与?

您遇到这个问题是因为中间件函数是作为闭包实现的。注意中间件函数定义为:

type MiddlewareFunc func(http.Handler) http.Handler

其中 http.Handler 是一个接口。所以你可以为每个中间件写这样的东西:

type MyMiddleware struct {
   // Fields your middleware func needs
   Next http.Handler
}

// This is the middleware func
func MW(next http.Handler) http.Handler {
   m:=MyMiddleware{Next:next}
   // Initialize other fields
   return m
}

// Implement http.Handler.
func (m MyMiddleware) ServeHTTP(wr http.ResponseWriter, req *http.Request) {
   // Do  middleware stuff
   m.Next.ServeHTTP(w,req)
}