转到:如何使用中间件模式?

I have a function that executes only with specific conditions (e.g. role == 'Administrator'). Now, I use 'if' statement. But it could be situations when number of conditions is high and 'if' with long definition looks not so esthetic.
Is it available mechanism in Go (or related with Go framework) allows implementation of middleware concept (action filters)?

For example, ASP.NET MVC allows to do this:

[MyFilter]
public ViewResult Index()
{
     // Filter will be applied to this specific action method
}

So, MyFilter() implemented in the separate class allows better code composition and testing.

Update: Revel (web framework for the Go) provides similar functionality with Interceptors (function that is invoked by the framework BEFORE or AFTER an action invocation): https://revel.github.io/manual/interceptors.html

This sort of thing is typically done with middleware in Go. The easiest is to show by example:

package main

import (
    "fmt"
    "html"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/foo", middleware(handler))

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}

func middleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        r.URL.Path = "/MODIFIED"

        // Run the next handler
        next.ServeHTTP(w, r)
    }
}

As you can see, a middleware is a function that:

  1. accepts a http.HandlerFunc as an argument;
  2. returns a http.HandlerFunc;
  3. calls the http.handlerFunc passed in.

With this basic technique you can "chain" as many middlewares as you like:

http.HandleFunc("/foo", another(middleware(handler)))

There are some variants to this pattern, and most Go frameworks use a slightly different syntax, but the concept is typically the same.

Revel (web framework for the Go) provides similar functionality with
Interceptors (function that is invoked by the framework BEFORE or AFTER an action invocation).
Concept and implementation described here: https://revel.github.io/manual/interceptors.html