gin是一款輕量級的go web開發框架,官方文檔
https://gin-gonic.com/docs/examples/
1.gin web項目結構
參考
https://github.com/voyagegroup/gin-boilerplate
gin+protobuf wire參考
https://github.com/mohuishou/blog-code/tree/main/01-go-training/04-project/10-layout
2.gin web quick start
https://gin-gonic.com/docs/quickstart/
在官方文檔中提供了2個quick start的demo,一個稍微複雜,一個比較簡單
簡單的例子如下,創建一個/ping接口,返回pong
package main import "github.com/gin-gonic/gin" func main() { r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run() // listen and serve on 0.0.0.0:8080 }
3.路由分組
如果gin項目的接口比較多的話,可以使用路由分組
https://gin-gonic.com/docs/examples/grouping-routes/
參考:【Go】基於 Gin 從0到1搭建 Web 管理後臺系統後端服務(三)路由、自定義校驗器和 Redis
4.數據綁定
將請求的參數傳遞給接口中的變量,需要使用gin的數據綁定
如果是path parameter
使用c.Param("name")
https://gin-gonic.com/docs/examples/param-in-path/
使用c.ShouldBindUri(&person)
https://gin-gonic.com/docs/examples/bind-uri/
如果是query parameter或者post請求的form-data
使用c.ShouldBind(&user)
https://gin-gonic.com/docs/examples/bind-query-or-post/
5.統一的response
可以如下定義統一的接口response,其中的interface{}類似java中的泛型T
type ControllerResponse struct { Code int Msg string Data interface{} } func Response(ctx *gin.Context, code int, msg string, data interface{}) { resp := ControllerResponse{Code: code, Msg: msg, Data: data} ctx.JSON(code, resp) ctx.Abort() } func Success(ctx *gin.Context, msg string, data interface{}) { Response(ctx, 200, msg, data) } func Fail(ctx *gin.Context, msg string, data interface{}) { Response(ctx, 500, msg, data) }
參考:go語言web開發系列之十五:gin框架統一定義API錯誤碼
6.middleware中間件
1.使用middleware
下面定義了3個middleware
// MiddleWare1 定義中間件1 func MiddleWare1() gin.HandlerFunc { return func(c *gin.Context) { fmt.Println("前 m1") c.Next() fmt.Println("後 m1") } } // MiddleWare2 定義中間件2 func MiddleWare2() gin.HandlerFunc { return func(c *gin.Context) { fmt.Println("前 m2") c.Next() fmt.Println("後 m2") } } // MiddleWare3 定義中間件3 func MiddleWare3() gin.HandlerFunc { return func(c *gin.Context) { fmt.Println("前 m3") c.Next() fmt.Println("後 m3") } }
在gin中添加middleware
func main() { // 創建路由 engine := gin.Default() // 註冊中間件 engine.Use(MiddleWare1(), MiddleWare2(), MiddleWare3()) // 路由規則 engine.GET("/ping", func(c *gin.Context) { fmt.Println("hello world") c.JSON(200, gin.H{"msg": "pong"}) }) err:=engine.Run(":3000") if err != nil { fmt.Println(err) } }
輸出如下
前 m1 前 m2 前 m3 hello world 後 m3 後 m2 後 m1 [GIN] 2023/12/25 - 00:06:11 | 200 | 35.726µs | 127.0.0.1 | GET "/ping"
接口返回pong
2.Next()和Abort()
Next()之前的代碼會在執行HandlerFunc之前執行,之後的代碼會在執行HandlerFunc之後執行
如果將middleware2中的c.Next()修改成c.Abort()
// MiddleWare2 定義中間件2 func MiddleWare2() gin.HandlerFunc { return func(c *gin.Context) { fmt.Println("前 m2") c.Abort() fmt.Println("後 m2") } }
則輸出將會如下
前 m1 前 m2 後 m2 後 m1 [GIN] 2023/12/25 - 00:11:05 | 200 | 16.262µs | 127.0.0.1 | GET "/ping"
接口無返回
可以Abort()不會阻止當前middleware的執行,但是會中止下游middleware以及HandlerFunc的執行
參考:[Go Package] gin 中間件流程控制:c.Next() / c.Abort()