中间件是一种计算机软件,可为操作系统提供的软件应用程序提供服务,以便于各个软件之间的沟通,特别是系统软件和应用软件。广泛用于web应用和面向服务的体系结构等。纵观GO语言,中间件应用比较普遍,主要应用:记录对服务器发送的请求(request)处理服务器响应(response )请求和处理之间做一个权限认证工作远程调用安全等等中间件处理程序是简单的http.Handler,它包装另一个http.Handler做请求的一些预处理和/或后处理。它被称为“中间件”,因为它位于Go Web服务器和实际处理程序之间的中间位置。下面是一些中间件例子记录日志中间件package mainimport ( “fmt” “log” “net/http”)func logging(f http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { log.Println(r.URL.Path) f(w, r) }}func foo(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, “foo”)}func bar(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, “bar”)}func main() { http.HandleFunc("/foo", logging(foo)) http.HandleFunc("/bar", logging(bar)) http.ListenAndServe(":8080", nil)}访问 http://localhost:8080/foo返回结果foo将上面示例修改下,也可以实现相同的功能。package mainimport ( “fmt” “log” “net/http”)func foo(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, “foo”)}func bar(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, “bar”)}func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println(r.URL.Path) next.ServeHTTP(w, r) })}func main() { http.Handle("/foo", loggingMiddleware(http.HandlerFunc(foo))) http.Handle("/bar", loggingMiddleware(http.HandlerFunc(bar))) http.ListenAndServe(":8080", nil)}访问 http://localhost:8080/foo返回结果foo多中间件例子package mainimport ( “fmt” “log” “net/http” “time”)type Middleware func(http.HandlerFunc) http.HandlerFunc// Logging logs all requests with its path and the time it took to processfunc Logging() Middleware { // Create a new Middleware return func(f http.HandlerFunc) http.HandlerFunc { // Define the http.HandlerFunc return func(w http.ResponseWriter, r *http.Request) { // Do middleware things start := time.Now() defer func() { log.Println(r.URL.Path, time.Since(start)) }() // Call the next middleware/handler in chain f(w, r) } }}// Method ensures that url can only be requested with a specific method, else returns a 400 Bad Requestfunc Method(m string) Middleware { // Create a new Middleware return func(f http.HandlerFunc) http.HandlerFunc { // Define the http.HandlerFunc return func(w http.ResponseWriter, r *http.Request) { // Do middleware things if r.Method != m { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } // Call the next middleware/handler in chain f(w, r) } }}// Chain applies middlewares to a http.HandlerFuncfunc Chain(f http.HandlerFunc, middlewares …Middleware) http.HandlerFunc { for _, m := range middlewares { f = m(f) } return f}func Hello(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, “hello world”)}func main() { http.HandleFunc("/", Chain(Hello, Method(“GET”), Logging())) http.ListenAndServe(":8080", nil)}中间件本身只是将其http.HandlerFunc作为其参数之一,包装它并返回一个新http.HandlerFunc的服务器来调用。在这里,我们定义了一种新类型Middleware,最终可以更容易地将多个中间件链接在一起。当然我们也可以改成如下形式package mainimport ( “fmt” “log” “net/http” “time”)type Middleware func(http.Handler) http.Handlerfunc Hello(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, “hello world”)}func Chain(f http.Handler, mmap …Middleware) http.Handler { for _, m := range mmap { f = m(f) } return f}func Method(m string) Middleware { return func(f http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println(r.URL.Path) if r.Method != m { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } f.ServeHTTP(w, r) }) }}func Logging() Middleware { return func(f http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { //log.Println(r.URL.Path) // Do middleware things start := time.Now() defer func() { log.Println(r.URL.Path, time.Since(start)) }() f.ServeHTTP(w, r) }) }}func main() { http.Handle("/", Chain(http.HandlerFunc(Hello), Method(“GET”), Logging())) http.ListenAndServe(":8080", nil)}在gin框架下实现中间件r := gin.Default() 创建带有默认中间件的路由,默认是包含logger和recovery中间件的r :=gin.new() 创建带有没有中间件的路由示例package mainimport ( “github.com/gin-gonic/gin” “log” “time”)func Logger() gin.HandlerFunc { return func(c *gin.Context) { t := time.Now() // Set example variable c.Set(“example”, “12345”) // before request c.Next() // after request latency := time.Since(t) log.Print(latency) //时间 0s // access the status we are sending status := c.Writer.Status() log.Println(status) //状态 200 }}func main() { r := gin.New() r.Use(Logger()) r.GET("/test", func(c *gin.Context) { example := c.MustGet(“example”).(string) // it would print: “12345” log.Println(example) }) // Listen and serve on 0.0.0.0:8080 r.Run(":8080")}以上示例也可改为package mainimport ( “github.com/gin-gonic/gin” “log” “time”)func Logger() gin.HandlerFunc { return func(c *gin.Context) { t := time.Now() // Set example variable c.Set(“example”, “12345”) // before request c.Next() // after request latency := time.Since(t) log.Print(latency) //时间 0s // access the status we are sending status := c.Writer.Status() log.Println(status) //状态 200 }}func main() { r := gin.New() r.GET("/test", Logger(), func(c *gin.Context) { example := c.MustGet(“example”).(string) // it would print: “12345” log.Println(example) }) // Listen and serve on 0.0.0.0:8080 r.Run(":8080")}即不用r.use添加中间件,直接将Logger() 写到r.GET 方法的参数里("/test"之后)。更多gin中间件示例可参考 https://github.com/gin-gonic/gin参考资料https://drstearns.github.io/t…https://gowebexamples.com/adv…更多GO学习资料