<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          GO 中間件 Middleware

          共 11595字,需瀏覽 24分鐘

           ·

          2021-08-09 02:20

          中間件是什么?Go 項目中引入中間件的目的和效果如何?本文詳細介紹了Golang 中間件。

          中間件是一種計算機 軟件,可為 操作系統(tǒng) 提供的 軟件應(yīng)用程序 提供服務(wù),以便于各個軟件之間的溝通,特別是系統(tǒng)軟件和應(yīng)用軟件。廣泛用于 web 應(yīng)用和面向服務(wù)的體系結(jié)構(gòu)等。

          縱觀 GO 語言,中間件應(yīng)用比較普遍,主要應(yīng)用:

          • 記錄對服務(wù)器發(fā)送的請求(request)
          • 處理服務(wù)器響應(yīng)(response )
          • 請求和處理之間做一個權(quán)限認證工作
          • 遠程調(diào)用
          • 安全
          • 等等

          中間件處理程序是簡單的http.Handler,它包裝另一個http.Handler做請求的一些預(yù)處理和/或后處理。它被稱為“中間件”,因為它位于 Go Web 服務(wù)器和實際處理程序之間的中間位置。

          下面是一些中間件例子

          記錄日志中間件

          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

          返回結(jié)果

          foo

          將上面示例修改下,也可以實現(xiàn)相同的功能。

          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

          返回結(jié)果

          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作為其參數(shù)之一,包裝它并返回一個新http.HandlerFunc的服務(wù)器來調(diào)用。在這里,我們定義了一種新類型Middleware,最終可以更容易地將多個中間件鏈接在一起。

          當(dāng)然我們也可以改成如下形式

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

          在 gin 框架下實現(xiàn)中間件

          r := gin.Default() 創(chuàng)建帶有默認中間件的路由,默認是包含 logger 和 recovery 中間件的
          r :=gin.new()      創(chuàng)建帶有沒有中間件的路由

          示例

          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) //狀態(tài) 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) //狀態(tài) 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 方法的參數(shù)里("/test"之后)。

          更多 gin 中間件示例可參考 https://github.com/gin-gonic/gin

          轉(zhuǎn)自:guyan0319

          segmentfault.com/a/1190000018819804

          文章轉(zhuǎn)載:Go開發(fā)大全
          (版權(quán)歸原作者所有,侵刪)


          點擊下方“閱讀原文”查看更多

          瀏覽 29
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一级黄色大片 | 久久久久亚洲 | 黄片免费观看 | 青青草偷窥美女屄 | 豆花视频成人版www |