如何建構有效的中介軟體
組成部分
中介軟體通常由兩個部分組成:
-
第一部分在你初始化中介軟體時執行一次。這是你設定全域物件、配置邏輯等的地方——所有只需要在應用程式生命週期中發生一次的事情。
-
第二部分在每次請求時執行。例如,在資料庫中介軟體中,你會將全域資料庫物件注入到請求上下文中。一旦它在上下文中,其他中介軟體和處理函式就可以擷取和使用它。
func funcName(params string) gin.HandlerFunc { // <--- // This is part one // ---> // Example initialization: validate input params if err := check(params); err != nil { panic(err) }
return func(c *gin.Context) { // <--- // This is part two // ---> // Example execution per request: inject into context c.Set("TestVar", params) c.Next() }}執行流程
讓我們來看以下範例程式碼:
func main() { router := gin.Default()
router.Use(globalMiddleware())
router.GET("/rest/n/api/*some", mid1(), mid2(), handler)
router.Run()}
func globalMiddleware() gin.HandlerFunc { fmt.Println("globalMiddleware...1")
return func(c *gin.Context) { fmt.Println("globalMiddleware...2") c.Next() fmt.Println("globalMiddleware...3") }}
func handler(c *gin.Context) { fmt.Println("exec handler.")}
func mid1() gin.HandlerFunc { fmt.Println("mid1...1")
return func(c *gin.Context) {
fmt.Println("mid1...2") c.Next() fmt.Println("mid1...3") }}
func mid2() gin.HandlerFunc { fmt.Println("mid2...1")
return func(c *gin.Context) { fmt.Println("mid2...2") c.Next() fmt.Println("mid2...3") }}根據上面的組成部分章節,當你執行 Gin 程序時,每個中介軟體的第一部分會先執行並列印以下資訊:
globalMiddleware...1mid1...1mid2...1初始化順序為:
globalMiddleware...1 | vmid1...1 | vmid2...1當你發送請求時——例如 curl -v localhost:8080/rest/n/api/some——每個中介軟體的第二部分會依序執行並輸出以下內容:
globalMiddleware...2mid1...2mid2...2exec handler.mid2...3mid1...3globalMiddleware...3換句話說,執行順序為:
globalMiddleware...2 | vmid1...2 | vmid2...2 | vexec handler. | vmid2...3 | vmid1...3 | vglobalMiddleware...3