zoukankan      html  css  js  c++  java
  • 中间件

    1. Gin中间件

    Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。

    2. 注册中间件

    Gin中的中间件必须是一个gin.HandlerFunc类型。例如我们像下面的代码一样定义一个统计请求耗时的中间件。

    package main
    
    import (
    	"github.com/gin-gonic/gin"
    	"time"
    	"log"
    )
    
    func main() {
    	
    }
    
    // StatCost 是一个统计耗时请求耗时的中间件
    func StatCost() gin.HandlerFunc { //HandlerFunc是一个函数类型,函数的参数是Context的指针类型
    	return func(c *gin.Context) {
    		start := time.Now()
    		c.Set("name", "小王子") // 可以通过c.Set在请求上下文中设置值,后续的处理函数能够取到该值
    		// 调用该请求的剩余处理程序
    		c.Next()
    		// 不调用该请求的剩余处理程序
    		// c.Abort()
    		// 计算耗时
    		cost := time.Since(start)
    		log.Println(cost)
    	}
    }
    

    3. 全局注册

    Use源码:

    Next执行流程:

    4. 为某个路由注册中间件

    // 给/test2路由单独注册中间件(可注册多个)
    	r.GET("/test2", StatCost(), func(c *gin.Context) {
    		name := c.MustGet("name").(string) // 从上下文取值
    		log.Println(name)
    		c.JSON(http.StatusOK, gin.H{
    			"message": "Hello world!",
    		})
    	})
    

    5. 为路由组注册中间件

    为路由组注册中间件有以下两种写法。

    写法1:

    shopGroup := r.Group("/shop", StatCost())
    {
        shopGroup.GET("/index", func(c *gin.Context) {...})
        ...
    }

    写法2:

    shopGroup := r.Group("/shop")
    shopGroup.Use(StatCost())
    {
        shopGroup.GET("/index", func(c *gin.Context) {...})
        ...
    }
    

    6. 上下文c设置值和取值

    7. 中间件注意事项

    gin默认中间件

    gin.Default()默认使用了LoggerRecovery中间件,其中:

    • Logger中间件将日志写入gin.DefaultWriter,即使配置了GIN_MODE=release
    • Recovery中间件会recover任何panic。如果有panic的话,会写入500响应码。

    如果不想使用上面两个默认的中间件,可以使用gin.New()新建一个没有任何默认中间件的路由。

    gin中间件中使用goroutine

    当在中间件或handler中启动新的goroutine时,不能使用原始的上下文(c *gin.Context),必须使用其只读副本(c.Copy())。

    package main
    
    import (
    	"github.com/gin-gonic/gin"
    	"log"
    )
    
    
    
    func main() {
    	r := gin.Default()
    
    	// async异步
    	// sync同步
    	r.GET("/long_async", func(c *gin.Context) {
    
    		// 创建要在goroutine中使用的副本
    		cCp := c.Copy()
    		go func() {
    
    			// 这里使用你创建的副本
    			log.Println("Done! in path ccp " + cCp.Request.URL.Path)
    			log.Println("Done! in path c " + c.Request.URL.Path) // c是可行的???
    			log.Println("Done! in path c " + c.Request.Method) // c是可行的???
    		}()
    	})
    
    	r.GET("/long_sync", func(c *gin.Context) {
    
    		// 这里没有使用goroutine,所以不用使用副本
    		log.Println("Done! in path " + c.Request.URL.Path)
    	})
    
    	r.Run(":8080")
    }
  • 相关阅读:
    2.3 节的练习
    2.2 节的练习--Compiler principles, technologys, &tools
    web测试点整理(二) -- 输入框
    web测试点整理 -- 注册/登录
    产品测试的思路
    C语言学习--静态链接库和动态链接库
    C语言学习(四)--操作符
    C语言学习(三)--语句
    C语言学习(二)--数据类型
    C语言学习(一)--基本概念
  • 原文地址:https://www.cnblogs.com/yzg-14/p/13142144.html
Copyright © 2011-2022 走看看