Go学习第十七章——Gin中间件与路由

这篇具有很好参考价值的文章主要介绍了Go学习第十七章——Gin中间件与路由。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 单独注册中间件

Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等
即比如,如果访问一个网页的话,不管访问什么路径都需要进行登录,此时就需要为所有路径的处理函数进行统一一个中间件

Gin中的中间件必须是一个gin.HandlerFunc类型

1.1 入门案例

我们先看一下Get函数能够接收的参数:

func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
	return group.handle(http.MethodGet, relativePath, handlers)
}

type HandlerFunc func(*Context)

从这个函数里,我们能看到它可以,它可以接收很多的HandlerFunc类型的数据,并且发现是func(*Context)数据类型都可以,所以,我们可以定义很多个中间件,它必须是*gin.Context类型

  1. 定义一个中间件
func m1(c *gin.Context) {
    fmt.Println("m1 in.........")
}
  1. 写一个函数,在前端响应的数据,作为参考
func indexHandler(c *gin.Context) {
    fmt.Println("index.....")
    c.JSON(http.StatusOK, gin.H{
       "msg": "index",
    })
}
  1. 完整代码
func indexHandler(c *gin.Context) {
    fmt.Println("index.....")
    c.JSON(http.StatusOK, gin.H{
       "msg": "index",
    })
}

// 定义一个中间件
func m1(c *gin.Context) {
    fmt.Println("m1 in.........")
}

func main() {
    r := gin.Default()
    //m1处于indexHandler函数的前面,请求来之后,先走m1,再走index
    r.GET("/index", m1, indexHandler)

    r.Run(":8000")
}

注意:m1处于indexHandler函数的前面,请求来之后,先走m1,再走index

然后,使用游览器访问对应的请求,看一下输出:

Go学习第十七章——Gin中间件与路由,golang,学习,gin,开发语言,笔记,后端

验证完毕!!~

1.2 多个中间件

router.GET,后面可以跟很多HandlerFunc方法,这些方法其实都可以叫中间件

package main

import (
  "fmt"
  "github.com/gin-gonic/gin"
)

func m1(c *gin.Context) {
  fmt.Println("m1 ...in")
}
func m2(c *gin.Context) {
  fmt.Println("m2 ...in")
}

func main() {
  router := gin.Default()

  router.GET("/", m1, func(c *gin.Context) {
    fmt.Println("index ...")
    c.JSON(200, gin.H{"msg": "响应数据"})
  }, m2)

  router.Run(":8080")
}

这里就不演示了~~

1.3 中间件拦截响应

c.Abort()函数,作用:拦截,后续的HandlerFunc就不会执行了

package main

import (
  "fmt"
  "github.com/gin-gonic/gin"
)

func m1(c *gin.Context) {
  fmt.Println("m1 ...in")
  c.JSON(200, gin.H{"msg": "第一个中间件拦截了"})
  c.Abort()
}
func m2(c *gin.Context) {
  fmt.Println("m2 ...in")
}

func main() {
  router := gin.Default()

  router.GET("/", m1, func(c *gin.Context) {
    fmt.Println("index ...")
    c.JSON(200, gin.H{"msg": "响应数据"})
  }, m2)

  router.Run(":8080")
}

运行后,去游览器试一下,会发现只输出:m1 …in,也就是被第一个拦截器拦截了~

1.4 中间件放行

c.Next()函数,作用:Next前后形成了其他语言中的请求中间件和响应中间件

package main

import (
  "fmt"
  "github.com/gin-gonic/gin"
)

func m1(c *gin.Context) {
  fmt.Println("m1 ...in")
  c.Next()
  fmt.Println("m1 ...out")
}
func m2(c *gin.Context) {
  fmt.Println("m2 ...in")
  c.Next()
  fmt.Println("m2 ...out")
}

func main() {
  router := gin.Default()

  router.GET("/", m1, func(c *gin.Context) {
    fmt.Println("index ...in")
    c.JSON(200, gin.H{"msg": "响应数据"})
    c.Next()
    fmt.Println("index ...out")
  }, m2)

  router.Run(":8080")
}

输出结果:

m1 ...in
index ...in 
m2 ...in    
m2 ...out   
index ...out
m1 ...out   

输出的方式,有点像栈,先进去的m1...out最后再输出~

2 全局注册中间件

在Gin框架中,可以使用Use方法注册全局中间件。全局中间件会对所有的请求都生效。

func main() {
    r := gin.Default()

    r.Use(Logger()) // 注册全局中间件

    r.GET("/hello", HelloHandler)

    r.Run(":8080")
}

// Logger 是一个全局中间件
func Logger() gin.HandlerFunc {
    return func(c *gin.Context) {
        start := time.Now()

        c.Next()

        end := time.Now()
        latency := end.Sub(start)

        log.Printf("[%s] %s %s %v", c.Request.Method, c.Request.URL.Path, c.Request.RemoteAddr, latency)
    }
}

func HelloHandler(c *gin.Context) {
    c.String(http.StatusOK, "Hello, Gin!")
}

在上面的示例中,Logger函数是一个全局中间件。它在处理请求之前记录了请求的相关信息,并在请求处理完成后打印了请求的耗时。

3 自定义参数传递

在中间件之间传递自定义参数是一种常见的需求。在Gin框架中,可以使用Context.SetContext.Get方法来传递自定义参数,并且传递的数据是一个key-value

func main() {
    r := gin.Default()

    r.Use(AddCustomData("custom data"))

    r.GET("/hello", HelloHandler)

    r.Run(":8080")
}

func AddCustomData(data string) gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Set("customData", data) // 设置自定义参数

        c.Next()
    }
}

func HelloHandler(c *gin.Context) {
    customData, exists := c.Get("customData") // 获取自定义参数

    if exists {
        c.String(http.StatusOK, "Hello, Gin! Custom data: %s", customData)
    } else {
        c.String(http.StatusOK, "Hello, Gin!")
    }
}

在上面的示例中,AddCustomData函数返回了一个中间件函数,用于在Context中设置自定义参数。在HelloHandler处理函数中,通过Context.Get方法获取自定义参数并使用。

4 路由分组

4.1 入门案例

将一系列的路由放到一个组下,统一管理。例如,以下的路由前面统一加上api的前缀

package main

import "github.com/gin-gonic/gin"

func main() {
  router := gin.Default()

  r := router.Group("/api")
  r.GET("/index", func(c *gin.Context) {
    c.String(200, "index")
  })
  r.GET("/home", func(c *gin.Context) {
    c.String(200, "home")
  })

  router.Run(":8080")
}

4.2 路由分组注册中间件

package main

import (
  "fmt"
  "github.com/gin-gonic/gin"
)

func middle(c *gin.Context) {
  fmt.Println("middle ...in")
}

func main() {
  router := gin.Default()

  r := router.Group("/api").Use(middle)  // 可以链式,也可以直接r.Use(middle)
  r.GET("/index", func(c *gin.Context) {
    c.String(200, "index")
  })
  r.GET("/home", func(c *gin.Context) {
    c.String(200, "home")
  })

  router.Run(":8080")
}

这样写我们就可以指定哪一些分组下可以使用中间件了

当然,中间件还有一种写法,就是使用函数加括号的形式

package main

import (
  "fmt"
  "github.com/gin-gonic/gin"
)

func middle(c *gin.Context) {
  fmt.Println("middle ...in")
}
func middle1() gin.HandlerFunc {
  // 这里的代码是程序一开始就会执行
  return func(c *gin.Context) {
    // 这里是请求来了才会执行
    fmt.Println("middle1 ...inin")
  }
}

func main() {
  router := gin.Default()

  r := router.Group("/api").Use(middle, middle1())
  r.GET("/index", func(c *gin.Context) {
    c.String(200, "index")
  })
  r.GET("/home", func(c *gin.Context) {
    c.String(200, "home")
  })

  router.Run(":8080")
}

4.3 综合使用

设置了一个中间件进行身份验证,并且还对路由进行分组,分为两组来使用

func main() {
    r := gin.Default()

    r.Use(Logger()) // 注册全局中间件

    v1 := r.Group("/v1")
    v1.Use(Auth()) // 注册 v1 路由组的局部中间件
    {
        v1.GET("/hello", HelloHandler)
        v1.GET("/user", UserHandler)
    }

    r.GET("/hello", HelloHandler) // 其他路由不使用 Auth 中间件

    r.Run(":8080")
}

func Auth() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 进行身份验证的逻辑

        if IsAuthenticated {
            c.Next()
        } else {
            c.AbortWithStatus(http.StatusUnauthorized)
        }
    }
}

func HelloHandler(c *gin.Context) {
    c.String(http.StatusOK, "Hello, Gin!")
}

func UserHandler(c *gin.Context) {
    c.String(http.StatusOK, "User Info")
}

// Logger 是一个全局中间件
func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()

		c.Next()

		end := time.Now()
		latency := end.Sub(start)

		log.Printf("[%s] %s %s %v", c.Request.Method, c.Request.URL.Path, c.Request.RemoteAddr, latency)
	}
}

5 使用内置的中间件

Gin框架内置了一些常用的中间件,可以直接使用。以下是一些常用的内置中间件和示例:

  • gin.Logger():记录请求日志
  • gin.Recovery():处理请求时的恢复机制
func main() {
    r := gin.Default()

    r.Use(gin.Logger()) // 使用 gin.Logger() 中间件
    r.Use(gin.Recovery()) // 使用 gin.Recovery() 中间件

    r.GET("/hello", HelloHandler)

    r.Run(":8000")
}

func HelloHandler(c *gin.Context) {
    c.String(http.StatusOK, "Hello, Gin!")
}

不过,平常我们不使用这两个中间件的时候,一样会有记录,所以我们看一下gin.Default函数

func Default() *Engine {
	debugPrintWARNINGDefault()
	engine := New()
	engine.Use(Logger(), Recovery())
	return engine
}

从这段代码就可以看出,是默认使用了这两个函数,一般自动调用了~~~

6 中间件案例

权限验证

以前后端最流行的jwt为例,如果用户登录了,前端发来的每一次请求都会在请求头上携带上token

后台拿到这个token进行校验,验证是否过期,是否非法

如果通过就说明这个用户是登录过的

不通过就说明用户没有登录

package main

import (
  "github.com/gin-gonic/gin"
)

func JwtTokenMiddleware(c *gin.Context) {
  // 获取请求头的token
  token := c.GetHeader("token")
  // 调用jwt的验证函数
  if token == "1234" {
    // 验证通过
    c.Next()
    return
  }
  // 验证不通过
  c.JSON(200, gin.H{"msg": "权限验证失败"})
  c.Abort()
}

func main() {
  router := gin.Default()

  api := router.Group("/api")

  apiUser := api.Group("")
  {
    apiUser.POST("login", func(c *gin.Context) {
      c.JSON(200, gin.H{"msg": "登录成功"})
    })
  }
  apiHome := api.Group("system").Use(JwtTokenMiddleware)
  {
    apiHome.GET("/index", func(c *gin.Context) {
      c.String(200, "index")
    })
    apiHome.GET("/home", func(c *gin.Context) {
      c.String(200, "home")
    })
  }

  router.Run(":8080")
}

耗时统计

统计每一个视图函数的执行时间文章来源地址https://www.toymoban.com/news/detail-729240.html

func TimeMiddleware(c *gin.Context) {
  startTime := time.Now()
  c.Next()
  since := time.Since(startTime)
  // 获取当前请求所对应的函数
  f := c.HandlerName()
  fmt.Printf("函数 %s 耗时 %d\n", f, since)
}

到了这里,关于Go学习第十七章——Gin中间件与路由的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Go Gin Gorm Casbin权限管理实现 - 3. 实现Gin鉴权中间件

    Casbin是用于Golang项目的功能强大且高效的开源访问控制库。 强大通用也意味着概念和配置较多,具体到实际应用(以Gin Web框架开发)需要解决以下问题: 权限配置的存储,以及 增删改查 Gin框架的中间件如何实现 经过一番摸索实践出经验,计划分为三个章节,循序渐进的介绍

    2024年02月07日
    浏览(32)
  • [每周一更]-(第83期):Go新项目-Gin中间件的使用和案例(10)

    在 Gin 中,中间件是一种用于处理 HTTP 请求和响应的功能强大的机制。中间件是一段位于请求处理链和最终处理器之间的代码, 它可以截获请求、执行预处理操作,修改请求或响应,然后将控制权传递给下一个中间件或最终的请求处理器。 中间件在业务使用中,方便注入一些

    2024年01月20日
    浏览(41)
  • gin中间件篇

    所有请求都经过此中间件 输出结果: 输出结果: 效果演示: 定义程序计时中间件,然后定义2个路由,执行函数后应该打印统计的执行时间,如下: 效果演示: 参考文章: https://www.fansimao.com/928855.html  gin Next()方法 - 范斯猫

    2024年01月21日
    浏览(28)
  • gin框架内容(三)--中间件

    gin框架内容(三)--中间件 Gin框架允许开发者在处理请求的过程中,加入用户自己的函数。这个函数就叫中间件,中间件适合处理一些公共的业务逻辑,比 如登录认证、权限校验、数据分页、记录日志、耗时统 计等 即比如,如果访问一个网页的话,不管访问什么路径都需要

    2024年02月15日
    浏览(34)
  • gin框架39--重构 BasicAuth 中间件

    每当我们打开一个网址的时候,会自动弹出一个认证界面,要求我们输入用户名和密码,这种BasicAuth是最基础、最常见的认证方式,gin框架中提供了一种内置的方式,但它只能用内置的用户和密码,无法使用外部db中的用户和密码,这种方式很多时候是不友好的。 为此,本文

    2024年02月08日
    浏览(31)
  • gin中使用限流中间件

    限流又称为流量控制(流控),通常是指限制到达系统的并发请求数,本文列举了常见的限流策略,并以gin框架为例演示了如何为项目添加限流组件。 限流又称为流量控制(流控),通常是指限制到达系统的并发请求数。 我们生活中也会经常遇到限流的场景,比如:某景区

    2024年01月25日
    浏览(35)
  • gin 中间件流程控制:Next()、 Abort()

    源码注释: Next 应该只在中间件内部使用。它执行调用处理程序内部链中的挂起处理程序。 通俗的说,就是中间件放行,当一个中间件代码执行到 Next() ,会先执行它之后的函数,最后再来执行完本函数。 eg: 如果其中一个中间件响应了c.Abort(),后续中间件将不再执行,直接按

    2024年02月15日
    浏览(48)
  • Gin框架: 控制器, 中间件的分层设计案例

    对控制器的分组与继承 1 )设计项目目录结构 2 )主程序 main.go 3 ) HTML模板目录配置 tpls/web/index.html 4 ) routers 配置 4.1 webRouters.go 4.2 apiRouters.go 4.2 adminRouters.go 5 ) controller 配置 5.1 web/webCtrl.go 5.2 api/apiCtrl.go 5.3 admin/indexCtrl.go 5.4 admin/baseCtrl.go 5.4 admin/userCtrl.go 以上就是对控制器的一

    2024年02月21日
    浏览(44)
  • 简单记录下gin中使用中间件记录操作日志

    1、直接定义中间件 2、在需要使用的地方直接使用就可以,自动会收集日志到数据库中

    2024年02月09日
    浏览(31)
  • Golang中Gin 参数绑定和验证的中间件

    1. 学习在Golang中使用Gin参数绑定和验证的中间件,了解不同参数类型的绑定和验证方式。 Gin框架提供了很多常用的中间件,其中就包括参数绑定和验证的中间件。在使用Gin框架中进行数据绑定和验证时,可以使用Gin内置的Binding、Validating和Uri中间件。 1. Binding Binding中间件用于

    2024年02月08日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包