golang gin後端開發框架(三)
1. 路由組
在實際的專案開發中,均是模組化開發
同一模組內的功能介面,往往會有相同的介面字首,這種可以用路由組來進行分類處理。
比如下面這幾組介面:
註冊:http://localhost:8080/user/register 登陸:http://localhost:8080/user/login 使用者資訊:http://localhost:8080/user/info
gin框架可以使用路由組來實現對路由的分類
路由組是router.Group中的一個方法,對於請求進行分組
func main() { engine := gin.Default() // 註冊路由組 routerGroup := engine.Group("/user") routerGroup.POST("/register", func(ctx *gin.Context) {}) routerGroup.POST("/login", func(ctx *gin.Context) {}) routerGroup.GET("/info", func(ctx *gin.Context) {}) engine.Run() }
2. 中介軟體
在實際的業務開發中,一個完整的系統可能要包含鑑權認證、許可權管理、安全檢查、日誌記錄等多個維度的系統支援
鑑權認證、許可權管理、安全檢查等業務都是屬於全系統的業務,和具體的業務沒有直接關聯
因此在開發中,為了更好的梳理系統架構,可以將以上這些業務單獨抽離出來,以外掛化的方式進行對接
這種通用業務獨立開發並靈活配置使用的元件,稱之為中介軟體,其位於伺服器和實際業務處理程式之間
2.1 gin的中介軟體
在gin中,中介軟體的型別定義如下:
// HandlerFunc defines the handler used by gin middleware as return value type HandlerFunc func(*Context)
HandlerFunc是一個函式型別,接收一個Context引數。用於編寫程式處理函式並返回HandleFunc型別,作為中介軟體定義
2.2 中介軟體Use用法
關於初始化gin engine的gin.Default()方法的實現中也使用了兩個中介軟體
// Default returns an Engine instance with the Logger and Recovery middleware already attached. func Default() *Engine { debugPrintWARNINGDefault() engine := New() engine.Use(Logger(), Recovery()) return engine }
我們可以跳轉到Logger()中介軟體的定義,去看看實現一箇中間件的格式是什麼
// Logger instances a Logger middleware that will write the logs to gin.DefaultWriter. // By default, gin.DefaultWriter = os.Stdout. func Logger() HandlerFunc { return LoggerWithConfig(LoggerConfig{}) }
2.3 自定義中介軟體
根據上文關於中介軟體的描述中,我們可以自定義一個特殊需求的中介軟體,中介軟體型別是函式,有兩條標準:
- func函式
- 返回值型別為HandlerFunc
比如我們現在有一個需求,實現一箇中間件,其功能就是打印出請求的path和method:
// RequestInfos 實現一箇中間件 func RequestInfos() gin.HandlerFunc { return func(ctx *gin.Context) { path := ctx.FullPath() method := ctx.Request.Method fmt.Println(path, method) } }
使用或者註冊中介軟體時有兩種方式,一種是直接使用engine.Use(),那麼所有介面都會經過這個中介軟體處理
// 使用中介軟體,所有介面都經過這個中介軟體 engine.Use(RequestInfos())
或者為某一個處理註冊一箇中間件,那麼只有這一個請求會經過該中介軟體
engine.GET("/query", RequestInfos(), func(ctx *gin.Context) { ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 1, "message": ctx.FullPath(), }) })
2.4 context.Next函式
在上面自定義中介軟體RequestInfos()中,列印了請求的路徑和請求的method,接著去執行了正常的業務處理函式
如果我們想輸出業務處理的結果,就應該使用context.Next來實現
context.Next可以將中介軟體程式碼一分為二:
- Next()之前的程式碼會在請求處理之前執行
- 當中間件執行流遇到context.Next時,會中斷執行,轉而執行業務邏輯
- 當業務邏輯執行完之後,再次回到Next函式處,繼續向下執行中介軟體邏輯,從而獲取業務執行之後的結果
具體用法如下:
// RequestInfos 實現一箇中間件 func RequestInfos() gin.HandlerFunc { return func(ctx *gin.Context) { path := ctx.FullPath() method := ctx.Request.Method fmt.Println(path, method) ctx.Next() // 在此處一分為二 fmt.Println(ctx.Writer.Status()) } }