Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。
1 单个路由注册中间件
// 统计耗时 的中间件func m1(c *gin.Context) {fmt.Println("m1 in ...")// 计时start := time.Now()c.Next() // 调用后续的处理函数// c.Abort() // 阻止调用后续的处理函数cost := time.Since(start)fmt.Printf("cost:%v\n", cost)fmt.Println("m1 out ...")}func indexHandler(c *gin.Context) {c.JSON(http.StatusOK, "index")}func main() {r := gin.Default()r.GET("/index", m1, indexHandler)r.Run("0.0.0.0:5000")}
2 全局路由注册中间件
(1) 全局注册中间件函数m1, m2
// 统计耗时 的中间件func m1(c *gin.Context) {fmt.Println("m1 in ...")// 计时start := time.Now()c.Next() // 调用后续的一个处理函数// c.Abort() // 阻止调用后续的所有处理函数cost := time.Since(start)fmt.Printf("cost:%v\n", cost)fmt.Println("m1 out ...")}func m2(c *gin.Context) {fmt.Println("m2 in ...")c.Next()fmt.Println("m2 out ...")}func indexHandler(c *gin.Context) {fmt.Println("index")c.JSON(http.StatusOK, "index")}func main() {r := gin.Default()r.Use(m1, m2) // 全局注册中间件函数m1, m2r.GET("/index", indexHandler)r.Run("0.0.0.0:5000")}
(2) 闭包
func login_required(doCheck bool) gin.HandlerFunc {return func(c *gin.Context) {if doCheck {// 获取token// 查询数据库获取user_idc.Set("user_id", 23)} else {c.Next()}}}func indexHandler(c *gin.Context) {fmt.Println("index")user_id, exists := c.Get("user_id")if !exists {fmt.Println("user_id不存在")} else {fmt.Println("user_id:", user_id)}c.JSON(http.StatusOK, "index")}func main() {r := gin.Default()r.Use(login_required(true))r.GET("/index", indexHandler)r.Run("0.0.0.0:5000")}
3 路由组注册中间件
func login_required(doCheck bool) gin.HandlerFunc {return func(c *gin.Context) {if doCheck {// 获取token// 查询数据库获取user_idc.Set("user_id", 23)} else {c.Next()}}}func main() {r := gin.Default()fooGroup := r.Group("/foo", login_required(true)){fooGroup.GET("/bar", func(c *gin.Context){user_id, exists := c.Get("user_id")if !exists {fmt.Println("user_id不存在")} else {fmt.Println("user_id:", user_id)}c.JSON(http.StatusOK, "foobar")})}r.Run("0.0.0.0:5000")}
4 注意事项
gin.Default()默认使用了Logger和Recovery中间件,其中:
- Logger中间件将日志写入gin.DefaultWriter,即使配置了GIN_MODE=release。
- Recovery中间件会recover任何panic。如果有panic的话,会写入500响应码。
如果不想使用上面两个默认的中间件,可以使用gin.New()新建一个没有任何默认中间件的路由。
当在中间件或handler中启动新的goroutine时,不能使用原始的上下文(c *gin.Context),必须使用其只读副本(c.Copy())。
