gin是一款轻量级的go web开发框架,官方文档
1 2
| https://gin-gonic.com/docs/examples/
|
1.gin web项目结构
参考
1 2
| https://github.com/voyagegroup/gin-boilerplate
|
gin+protobuf wire参考
1 2
| https://github.com/mohuishou/blog-code/tree/main/01-go-training/04-project/10-layout
|
2.gin web quick start
1 2
| https://gin-gonic.com/docs/quickstart/
|
在官方文档中提供了2个quick start的demo,一个稍微复杂,一个比较简单
简单的例子如下,创建一个/ping接口,返回pong
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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项目的接口比较多的话,可以使用路由分组
1 2
| https://gin-gonic.com/docs/examples/grouping-routes/
|
参考:【Go】基于 Gin 从0到1搭建 Web 管理后台系统后端服务(三)路由、自定义校验器和 Redis
4.数据绑定
将请求的参数传递给接口中的变量,需要使用gin的数据绑定
如果是path parameter
使用c.Param(“name”)
1 2
| https://gin-gonic.com/docs/examples/param-in-path/
|
使用c.ShouldBindUri(&person)
1 2
| https://gin-gonic.com/docs/examples/bind-uri/
|
如果是query parameter或者post请求的form-data
使用c.ShouldBind(&user)
1 2
| https://gin-gonic.com/docs/examples/bind-query-or-post/
|
5.统一的response
可以如下定义统一的接口response,其中的interface{}类似java中的泛型T
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| // 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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) } }
|
输出如下
1 2 3 4 5 6 7 8 9
| 前 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()
1 2 3 4 5 6 7 8 9
| // MiddleWare2 定义中间件2 func MiddleWare2() gin.HandlerFunc { return func(c *gin.Context) { fmt.Println("前 m2") c.Abort() fmt.Println("后 m2") } }
|
则输出将会如下
1 2 3 4 5 6
| 前 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()