中间件是一种计算机软件,可为操做系统提供的软件应用程序提供服务,以便于各个软件之间的沟通,特别是系统软件和应用软件。普遍用于web应用和面向服务的体系结构等。git
纵观GO语言,中间件应用比较广泛,主要应用:github
中间件处理程序是简单的http.Handler
,它包装另外一个http.Handler
作请求的一些预处理和/或后处理。它被称为“中间件”,由于它位于Go Web服务器和实际处理程序之间的中间位置。golang
下面是一些中间件例子web
package main import ( "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安全
返回结果服务器
fooapp
将上面示例修改下,也能够实现相同的功能。框架
package main import ( "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学习
返回结果url
foo
package main import ( "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 process func 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 Request func 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.HandlerFunc func 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 main import ( "fmt" "log" "net/http" "time" ) type Middleware func(http.Handler) http.Handler func 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) }
r := gin.Default() 建立带有默认中间件的路由,默认是包含logger和recovery中间件的 r :=gin.new() 建立带有没有中间件的路由
示例
package main import ( "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 main import ( "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
参考资料