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.局部中间件

参考:Golang Gin 局部、全局 中间件使用

7.在Gin中使用http handler中间件

除了使用gin的middleware来实现中间件之外,也可以使用Go的标准库的net/http包来初始http请求

参考:GO中间件(Middleware)

在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

 

posted @   tonglin0325  阅读(86)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 趁着过年的时候手搓了一个低代码框架
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现
点击右上角即可分享
微信分享提示