Golang?Gin?中間件?Next()方法示例詳解
Next()方法
- 在中間件中調(diào)用 next() 方法,會(huì)從 next() 方法調(diào)用的地方跳轉(zhuǎn)到
- Handler函數(shù)Handler函數(shù)執(zhí)行完成,若中間件還有部分代碼未執(zhí)行(中間件中next()之后的代碼),則執(zhí)行該代碼
如果第一個(gè)中間件處理直接使用了next函數(shù),直接跳轉(zhuǎn)到handler函數(shù),處理完之后還會(huì)回過來處理剩下的中間件函數(shù)。
除了最中心的這塊,其他的都是中間件,當(dāng)我一個(gè)中間件進(jìn)來,當(dāng)我直接使用了next之后,直接跳到業(yè)務(wù)處理這部分的handler,然后業(yè)務(wù)處理的handler處理完畢之后,然后它再回跳到一層一層未處理完的這個(gè)中間件代碼。
所以它就非常像洋蔥,它其實(shí)中間件是一層一層,但是前面只執(zhí)行了一半,處理完中間件之后是響應(yīng)了,響應(yīng)的時(shí)候還會(huì)再去處理剩下的這個(gè)中間件一層一層。
// 日志中間件 func MiddleWareLog() gin.HandlerFunc { //這里也是context,因?yàn)槟愕闹虚g件也是對(duì)請(qǐng)求和響應(yīng)的處理,只要涉及到請(qǐ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 "/"
首先可以看到我先注冊(cè)了log中間件,然后注冊(cè)了requestid中間件的id。所以說是按照注冊(cè)中間件的順序來的,然后會(huì)執(zhí)行完。
(1)如果上面中間件沒有加入next函數(shù),那么它會(huì)將中間件里面所有邏輯執(zhí)行完
(2)如果只有一層中間件,那么在中間件中調(diào)用 next() 方法,會(huì)從 next() 方法調(diào)用的地方跳轉(zhuǎn)到Handler函數(shù)。
如果有多層中間件,那么會(huì)跳轉(zhuǎn)到鏈表里面下一個(gè)中間件,上面就是從log中間件跳轉(zhuǎn)到request中間件了。在requestid中間件執(zhí)行了next函數(shù),它下面沒有中間件了,只有業(yè)務(wù)代碼了,那么就去執(zhí)行業(yè)務(wù)的handler,并且執(zhí)行好了之后我返回出去,最后執(zhí)行剩下的中間件那部分沒執(zhí)行完的邏輯。
其實(shí)和洋蔥一樣,最開始執(zhí)行的是最外面的一層,后執(zhí)行的是最里面的一層。但是業(yè)務(wù)代碼執(zhí)行完了之后,我從最里面這層開始
業(yè)務(wù)場(chǎng)景:最里面這一層的中間件,就是requestid了,可以去做一個(gè)開始的計(jì)時(shí),next()然后里面去執(zhí)行業(yè)務(wù)代碼,執(zhí)行完之后返回里面再來一個(gè)結(jié)束的計(jì)時(shí),那么就能夠拿到這個(gè)方法的執(zhí)行時(shí)間。
在寫一些微服務(wù)框架,做一個(gè)metric的展現(xiàn)的時(shí)候,其實(shí)都是借助中間件這么做的,然后將數(shù)據(jù)暴露給一個(gè)接口,然后Prometheus去拿一下,最后展現(xiàn)出來,就是這樣實(shí)現(xiàn)的。
實(shí)現(xiàn)token認(rèn)證
http://127.0.0.1:8080/index index首頁(yè)無需token直接訪問
http://127.0.0.1:8080/home home家目錄需要對(duì)token進(jìn)行驗(yàn)證,驗(yàn)證通過才可訪問
中間件最大的存儲(chǔ)長(zhǎng)度是60多,不能再往下存了。
c.abort()就是直接跳到鏈表最后一個(gè), 后面沒有了,那么也就執(zhí)行完了,其他的中間件就不執(zhí)行了。
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func AuthMiddleWare() gin.HandlerFunc { return func(c *gin.Context) { //常用場(chǎng)景,客戶端也就是接口的調(diào)用方,客戶端攜帶token的方式 1:請(qǐng)求頭(最常用) 2:請(qǐng)求體 3:uri token := c.Request.Header.Get("token") fmt.Println("獲取token信息:", token) if token != "qazw1234" { c.JSON(http.StatusOK, gin.H{ "msg": "身份驗(yàn)證不通過", }) //Abort方法用于跳到handler鏈表最后一個(gè)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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang 如何通過反射創(chuàng)建新對(duì)象
這篇文章主要介紹了golang 通過反射創(chuàng)建新對(duì)象的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-04-04Golang微服務(wù)框架Kratos實(shí)現(xiàn)Kafka消息隊(duì)列的方法
消息隊(duì)列是大型分布式系統(tǒng)不可缺少的中間件,也是高并發(fā)系統(tǒng)的基石中間件,所以掌握好消息隊(duì)列MQ就變得極其重要,在本文當(dāng)中,您將了解到:什么是消息隊(duì)列?什么是Kafka?怎樣在微服務(wù)框架Kratos當(dāng)中應(yīng)用Kafka進(jìn)行業(yè)務(wù)開發(fā),需要的朋友可以參考下2023-09-09從Context到go設(shè)計(jì)理念輕松上手教程
這篇文章主要為大家介紹了從Context到go設(shè)計(jì)理念輕松上手教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09