Golang?Gin?中間件?Next()方法示例詳解
Next()方法
- 在中間件中調(diào)用 next() 方法,會從 next() 方法調(diào)用的地方跳轉(zhuǎn)到
- Handler函數(shù)Handler函數(shù)執(zhí)行完成,若中間件還有部分代碼未執(zhí)行(中間件中next()之后的代碼),則執(zhí)行該代碼
如果第一個中間件處理直接使用了next函數(shù),直接跳轉(zhuǎn)到handler函數(shù),處理完之后還會回過來處理剩下的中間件函數(shù)。
除了最中心的這塊,其他的都是中間件,當(dāng)我一個中間件進(jìn)來,當(dāng)我直接使用了next之后,直接跳到業(yè)務(wù)處理這部分的handler,然后業(yè)務(wù)處理的handler處理完畢之后,然后它再回跳到一層一層未處理完的這個中間件代碼。
所以它就非常像洋蔥,它其實中間件是一層一層,但是前面只執(zhí)行了一半,處理完中間件之后是響應(yīng)了,響應(yīng)的時候還會再去處理剩下的這個中間件一層一層。
// 日志中間件 func MiddleWareLog() gin.HandlerFunc { //這里也是context,因為你的中間件也是對請求和響應(yīng)的處理,只要涉及到請求和響應(yīng)的處理就用到context上下文 return func(c *gin.Context) { fmt.Println("log start") c.Next() fmt.Println("log end") } } func MiddleWareRequestId() gin.HandlerFunc { return func(c *gin.Context) { fmt.Println("request id start") c.Next() fmt.Println("request id end") } } func main() { r := gin.Default() r.Use(MiddleWareLog(), MiddleWareRequestId()) r.GET("/", func(c *gin.Context) { fmt.Println("app handler.......") c.JSON(http.StatusOK, gin.H{ "msg": "success", }) }) r.Run(":8000") }
[GIN-debug] Listening and serving HTTP on :8000 log start request id start app handler....... request id end log end [GIN] 2023/04/08 - 09:51:03 | 200 | 2.2505ms | ::1 | GET "/"
首先可以看到我先注冊了log中間件,然后注冊了requestid中間件的id。所以說是按照注冊中間件的順序來的,然后會執(zhí)行完。
(1)如果上面中間件沒有加入next函數(shù),那么它會將中間件里面所有邏輯執(zhí)行完
(2)如果只有一層中間件,那么在中間件中調(diào)用 next() 方法,會從 next() 方法調(diào)用的地方跳轉(zhuǎn)到Handler函數(shù)。
如果有多層中間件,那么會跳轉(zhuǎn)到鏈表里面下一個中間件,上面就是從log中間件跳轉(zhuǎn)到request中間件了。在requestid中間件執(zhí)行了next函數(shù),它下面沒有中間件了,只有業(yè)務(wù)代碼了,那么就去執(zhí)行業(yè)務(wù)的handler,并且執(zhí)行好了之后我返回出去,最后執(zhí)行剩下的中間件那部分沒執(zhí)行完的邏輯。
其實和洋蔥一樣,最開始執(zhí)行的是最外面的一層,后執(zhí)行的是最里面的一層。但是業(yè)務(wù)代碼執(zhí)行完了之后,我從最里面這層開始
業(yè)務(wù)場景:最里面這一層的中間件,就是requestid了,可以去做一個開始的計時,next()然后里面去執(zhí)行業(yè)務(wù)代碼,執(zhí)行完之后返回里面再來一個結(jié)束的計時,那么就能夠拿到這個方法的執(zhí)行時間。
在寫一些微服務(wù)框架,做一個metric的展現(xiàn)的時候,其實都是借助中間件這么做的,然后將數(shù)據(jù)暴露給一個接口,然后Prometheus去拿一下,最后展現(xiàn)出來,就是這樣實現(xiàn)的。
實現(xiàn)token認(rèn)證
http://127.0.0.1:8080/index index首頁無需token直接訪問
http://127.0.0.1:8080/home home家目錄需要對token進(jìn)行驗證,驗證通過才可訪問
中間件最大的存儲長度是60多,不能再往下存了。
c.abort()就是直接跳到鏈表最后一個, 后面沒有了,那么也就執(zhí)行完了,其他的中間件就不執(zhí)行了。
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func AuthMiddleWare() gin.HandlerFunc { return func(c *gin.Context) { //常用場景,客戶端也就是接口的調(diào)用方,客戶端攜帶token的方式 1:請求頭(最常用) 2:請求體 3:uri token := c.Request.Header.Get("token") fmt.Println("獲取token信息:", token) if token != "qazw1234" { c.JSON(http.StatusOK, gin.H{ "msg": "身份驗證不通過", }) //Abort方法用于跳到handler鏈表最后一個index,相當(dāng)于直接退出,不執(zhí)行后面的handler了 c.Abort() return } } } func main() { r := gin.Default() r.GET("/home", AuthMiddleWare(), func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "msg": "home路由", }) }) r.Run(":8000") }
到此這篇關(guān)于Golang Gin 中間件 Next()方法的文章就介紹到這了,更多相關(guān)Golang Gin 中間件 Next內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang微服務(wù)框架Kratos實現(xiàn)Kafka消息隊列的方法
消息隊列是大型分布式系統(tǒng)不可缺少的中間件,也是高并發(fā)系統(tǒng)的基石中間件,所以掌握好消息隊列MQ就變得極其重要,在本文當(dāng)中,您將了解到:什么是消息隊列?什么是Kafka?怎樣在微服務(wù)框架Kratos當(dāng)中應(yīng)用Kafka進(jìn)行業(yè)務(wù)開發(fā),需要的朋友可以參考下2023-09-09