Gin框架
Gin框架 中间件
Gin 框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。 通俗的讲:中间件就是匹配路由前和匹配路由完成后执行的一系列操作 ## 路由中间件 Gin 中的中间件必须是一个 gin.HandlerFunc 类型,配置路由的时候可以传递多个 func 回调函数,最后一个 func 回调函数前面触发的方法都可以称为中间件 ```go func initMiddlewareOne(ctx *gin.Context) { fmt.Println("我是一个中间件1" ) func initMiddlewareTwo(ctx *gin.Context) { fmt.Println("我是一个中间件2" ) func main() { r := gin.Default() //一个中间件 r.GET("/", initMiddlewareOne, func(ctx *gin.Context) { ctx.String(200, "首页--中间件演示") }) //两个中间件 r.GET("/news", initMiddlewareOne, initMiddlewareTwo,func(ctx *gin.Context) { ctx.String(200, "新闻页面--中间件演示") }) } ``` ## 全局中间件 ```go func initMiddleware(ctx *gin.Context) { fmt.Println("全局中间件 通过 r.Use 配置") // 调用该请求的剩余处理程序 ctx.Next() } func main() { r := gin.Default() r.Use(initMiddleware) //使用中间件 r.GET("/", func(ctx *gin.Context) { ctx.String(200, "首页--中间件演示") }) }) r.Run(":8080") } ``` ## 在路由分组中配置中间件 - 方法一 ```go shopGroup := r.Group("/shop", initMiddleware()) { shopGroup.GET("/index", func(c *gin.Context) {...}) ... } ``` - 方法二 ```go shopGroup := r.Group("/shop") shopGroup.Use(initMiddleware()) { shopGroup.GET("/index", func(c *gin.Context) {...}) ... } ``` ## ctx.Next()调用该请求的剩余处理程序 >中间件里面加上 ctx.Next()可以让我们在路由匹配完成后执行一些操作。 - 比如我们统计一个请求的执行时间 ```go func initMiddleware(ctx *gin.Context) { fmt.Println("1-执行中中间件") start := time.Now().UnixNano() // 调用该请求的剩余处理程序 ctx.Next() fmt.Println("3-程序执行完成 计算时间") // 计算耗时 Go 语言中的 Since()函数保留时间值,并用于评估与实际时间的差异 end := time.Now().UnixNano() fmt.Println(end - start) } func main() { r := gin.Default() r.GET("/", initMiddleware, func(ctx *gin.Context) { fmt.Println("2- 执 行 首 页 返 回 数 据 ") ctx.String(200, "首页--中间件演示") }) r.GET("/news", initMiddleware, func(ctx *gin.Context) { ctx.String(200, "新闻页面--中间件演示") }) r.Run(":8080") } ``` - 一个路由配置多个中间件的执行顺序 ```go func initMiddlewareOne(ctx *gin.Context) { fmt.Println("initMiddlewareOne--1-执行中中间件") ctx.Next() fmt.Println("initMiddlewareOne--2-执行中中间件") } func initMiddlewareTwo(ctx *gin.Context) { fmt.Println("initMiddlewareTwo--1-执行中中间件") ctx.Next() fmt.Println("initMiddlewareTwo--2-执行中中间件") } func main() { r := gin.Default() r.GET("/", initMiddlewareOne, initMiddlewareTwo, func(ctx *gin.Context) { fmt.Println("执行路由里面的程序") ctx.String(200, "首页--中间件演示") }) r.Run(":8080") } //执行输出内容 initMiddlewareOne--1-执行中中间件 initMiddlewareTwo--1-执行中中间件 执行路由里面的程序 initMiddlewareTwo--2-执行中中间件 initMiddlewareOne--2-执行中中间件 ``` ## c.Abort()终止调用该请求的剩余处理程序 ```go func initMiddlewareOne(ctx *gin.Context) { fmt.Println("initMiddlewareOne--1-执行中中间件") // 调用该请求的剩余处理程序 ctx.Next() fmt.Println("initMiddlewareOne--2-执行中中间件") } func initMiddlewareTwo(ctx *gin.Context) { fmt.Println("initMiddlewareTwo--1-执行中中间件") // 终止调用该请求的剩余处理程序 ctx.Abort() fmt.Println("initMiddlewareTwo--2-执行中中间件") } func main() { r := gin.Default() r.GET("/", initMiddlewareOne, initMiddlewareTwo, func(ctx *gin.Context) { fmt.Println("执行路由里面的程序") ctx.String(200, "首页--中间件演示") }) r.Run(":8080") } //输出结果 initMiddlewareOne--1-执行中间件 initMiddlewareTwo--1-执行中间件 initMiddlewareTwo--2-执行中间件 initMiddlewareOne--2-执行中间件 ``` ## 中间件和对应控制器之间共享数据 - 设置值:ctx.Set("username", "张三") - 获取值:username, _ := ctx.Get("username") - 中间件设置值 ```go func InitAdminMiddleware(ctx *gin.Context) { fmt.Println("路由分组中间件") // 可以通过 ctx.Set 在请求上下文中设置值,后续的处理函数能够取到该值 ctx.Set("username", "张三") // 调用该请求的剩余处理程序 ctx.Next() } ``` - 控制器获取值 ```go func (c UserController) Index(ctx *gin.Context) { username, _ := ctx.Get("username") fmt.Println(username) //类型断言 v,ok := username.(string) if ok {} else {} ctx.String(http.StatusOK, "这是用户首页 111") } ``` ## 中间件注意事项 - gin 默认中间件 - gin.Default()默认使用了 Logger 和 Recovery 中间件,其中: - Logger 中间件将日志写入 gin.DefaultWriter,即使配置了 GIN_MODE=release。 - Recovery 中间件会 recover 任何 panic。如果有 panic 的话,会写入 500 响应码。 - 如果不想使用上面两个默认的中间件,可以使用 gin.New()新建一个没有任何默认中间件的路由。 - gin 中间件中使用 goroutine 当在中间件或 handler 中启动新的 goroutine 时,不能使用原始的上下文(c *gin.Context), 必须使用其只读副本(c.Copy()) ```go r.GET("/", func(c *gin.Context) { cCp := c.Copy() go func() { time.Sleep(5 * time.Second) // 这里使用你创建的副本 fmt.Println("Done! in path " + cCp.Request.URL.Path) }() c.String(200, "首页") }) ```
顶部
收展
底部
[TOC]
目录
Gin框架 安装
Gin框架 基本路由
Gin框架 路由传值与或参数
Gin框架 路由分组和抽离
Gin框架 自定义控制器
Gin框架 中间件
Gin框架 模板
相关推荐
Go标准库