Сокращение шаблонов в промежуточном программном обеспечении мультиплексора и реализации пользовательского контекста - PullRequest
4 голосов
/ 24 апреля 2020

Я довольно новичок в 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))
}

Это работает, но потом мне приходится иметь дело с большим количеством стандартного кода. Простейшее промежуточное программное обеспечение, реализованное в этом шаблоне, должно иметь как минимум два оператора возврата и множество объявлений функции наклона.

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)
        })
    }
}

Это быстро становится более серьезной проблемой, когда промежуточное программное обеспечение должно принимать некоторые дополнительные параметры, поскольку теперь оно приходится иметь дело с тремя операторами возврата:

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)
                // ...
            })
        }
    }
}

Есть ли способ, которым я могу уменьшить участие шаблонного кода?

1 Ответ

4 голосов
/ 26 апреля 2020

У вас есть эта проблема, потому что функции промежуточного программного обеспечения реализованы как замыкания. Обратите внимание, что функция промежуточного программного обеспечения определяется как:

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)
}
...