go学习笔记——gin框架
gin是一款轻量级的go web开发框架,官方文档
1 | https: //gin-gonic .com /docs/examples/ |
1.gin web项目结构
参考
1 | https: //github .com /voyagegroup/gin-boilerplate |
gin+protobuf wire参考
1 | https: //github .com /mohuishou/blog-code/tree/main/01-go-training/04-project/10-layout |
2.gin web quick start
1 | 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 | 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 | https: //gin-gonic .com /docs/examples/grouping-routes/ |
参考:【Go】基于 Gin 从0到1搭建 Web 管理后台系统后端服务(三)路由、自定义校验器和 Redis
4.数据绑定
将请求的参数传递给接口中的变量,需要使用gin的数据绑定
如果是path parameter
使用c.Param("name")
1 | https: //gin-gonic .com /docs/examples/param-in-path/ |
使用c.ShouldBindUri(&person)
1 | https: //gin-gonic .com /docs/examples/bind-uri/ |
如果是query parameter或者post请求的form-data
使用c.ShouldBind(&user)
1 | 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 | 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.Gin的middleware中间件
1.使用middleware
gin的middleware需要实现gin.HandlerFunc,可以用其来实现诸如jwt,auth等功能,参考
https://github.com/gin-gonic/contrib/blob/master/jwt/jwt.go
https://gin-gonic.com/zh-cn/docs/examples/using-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 | // 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 | 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 | 前 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 | // MiddleWare2 定义中间件2 func MiddleWare2() gin.HandlerFunc { return func(c *gin.Context) { fmt .Println( "前 m2" ) c.Abort() fmt .Println( "后 m2" ) } } |
则输出将会如下
1 2 3 4 5 | 前 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()
3.全局中间件和局部中间件
1.白名单
上面给出的例子中,middleware将对全部的请求生效,这里可以通过指定白名单的方法来使其只对部分请求生效
2.局部中间件
7.在Gin中使用http handler中间件
除了使用gin的middleware来实现中间件之外,也可以使用Go的标准库的net/http包来初始http请求
在gin中使用的话,需要将http.Handler转换成gin.HanlderFunc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // MiddleWare4 定义中间件4 func MiddleWare4(next http.Handler) http.Handler { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { fmt .Println( "前 m4" ) next.ServeHTTP(writer, request) fmt .Println( "后 m4" ) }) } // 将 http.Handler 包装成 Gin 中间件的函数 func WrapHandler(handler http.Handler) gin.HandlerFunc { return func(c *gin.Context) { handler.ServeHTTP(c.Writer, c.Request) c.Next() } } |
在router中添加middleware,注意需要将middleware写在局部路由的前面才能生效
1 2 3 4 5 6 7 8 9 | wrappedMiddleware := middleware.WrapHandler(middleware.MiddleWare4(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 空的 http.HandlerFunc,只为了包装中间件 }))) r.Use(wrappedMiddleware, middleware.MiddleWare1(), middleware.MiddleWare2()) // Ping test r.GET( "/ping" , func(c *gin.Context) { c.String(http.StatusOK, "pong" ) }) |
参考:https://github.com/go-kratos/examples/blob/main/http/middlewares/middlewares.go
本文只发表于博客园和tonglin0325的博客,作者:tonglin0325,转载请注明原文链接:https://www.cnblogs.com/tonglin0325/p/18183202
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步