
企業工商數據API用哪種?
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
它先使用New()
方法初始化一個引擎,然后再調用引擎的Use 方法,加載了兩個「中間件」
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
engine.RouterGroup.Use(middleware...)
engine.rebuild404Handlers()
engine.rebuild405Handlers()
return engine
}
加載了兩個gin中的中間件,Logger()與Recovery()
Logger()的源碼為
func Logger() HandlerFunc {
return LoggerWithConfig(LoggerConfig{})
}
Recovery() 的源碼為
func Recovery() HandlerFunc {
return RecoveryWithWriter(DefaultErrorWriter)
}
中間件為一類函數,「HandlerFunc」 , 定義為 type HandlerFunc func(*Context)
也就是該函數的參數為Context
,也就是說,如果我們要自定義一個中間件函數的話,只需要返回一個參數為(*gin.Content)
的函數即可。
何為中間件?當一個請求到達gin服務的某個路由以后,gin 會根據路由中定義好的處理類來進行處理,以GET方法為例
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle(http.MethodGet, relativePath, handlers)
}
handlers 為不定參數,也就是說可以有多個處理類,而這里的處理類類型也是HandlerFunc,和中間件是一樣的。
可以理解為是中間件為多個處理請求的Handler,某個請求先經過一個Handler, 之后再經過第二個,第三個,最后將結果返回給調用者。
中間件函數中有以下兩個方法比較重要
Next()
方法,該中間件處理以后,交由下一個中間件處理
Abort()
方法,調用完該方法以后,之后的HandlerFunc則不進行處理了
package midwares
import (
"fmt"
"github.com/gin-gonic/gin"
"time"
)
//打印耗時的中間件
func Checktime() gin.HandlerFunc {
//這里可以處理一些別的邏輯
return func(c *gin.Context) {
start := time.Now()
c.Next()
spend:= time.Since(start).Microseconds()
fmt.Printf("use: %d \n", spend)
}
}
func Abort(c *gin.Context){
fmt.Println("使用了Abort中間件,不會進行之后處理")
c.JSON(200, gin.H{"msg": "no next"})
c.Abort()
}
這兩種方式效果是一樣的,只是在gin初始化加載的方式不同
r := gin.Default()
r.Use(midwares.Checktime()) //需要加上()
r.Use(midwares.Abort) // 不需要加上()
個人還是比較喜歡加上()的方式。
中間件有兩種使用方式,一種是全局的中間件,一種是局部中間件
如上面的使用r.Use(midware)
的方式是全局的,這種方式,每個路由都會走該中間件的邏輯。
局部中間件為在路由定義時使用,這種定義則只在該路由上有效.
userv1.GET("/abort", midwares.Abort, userv1_h.Abort)
上面我定義了兩個中間件,Checktime
為記錄下該請求所用的時間,Abort
中間件為測試c.Abort
函數功能,使用了該中間件的路由只會走到這里,不會再經過之后的路由了。
訪問上面的路由地址?/abort
?以下,控制臺會輸出
使用了Abort中間件,不會進行之后處理
use: 443
第一行輸出為「Abort」 中間件的輸出,第二行輸出為「Checktime」中間件的輸出。
http的返回為Abort中間件定義的返回,之后的HandlerFunc不再執行了。
{
msg: "no next"
}
創建一個中間件,如果校驗成功則繼續往下走,如果不是管理員,則就不要往下走了,返回401
func CheckAdmin() gin.HandlerFunc{
return func(c *gin.Context) {
username := c.Query("user")
// 這里可以是從cookie或者 session 中判斷
if username == "admin"{
c.Next()
}else{
c.JSON(401, gin.H{"msg": "No Private"})
c.Abort()
}
}
}
gin在初始化的時候加載了一些中間件,又定義了全局的中間件,又定義了路由的中間件,那么這些中間件的執行順序是如何的呢?
執行的順序為 全局中間件 > 路由組中間件 > 路由中間件。
Gin框架入門(四)—中間件[1]
本文章轉載微信公眾號@序語程言