中间件

gin中间件

全局

package main

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

func userFunc(context *gin.Context) {
	fmt.Println("userFunc函数")
	context.JSON(http.StatusOK, gin.H{
		"msg": "ok",
	})
}

func indexFunc(context *gin.Context) {
	fmt.Println("indexFunc函数")
	context.JSON(http.StatusOK, gin.H{
		"msg": "ok",
	})
}

//中间件
func midFunc(context *gin.Context) {
	fmt.Println("midFunc中间件")
	start := time.Now()
	context.Next() //调用后续处理的函数
	//context.Abort()//阻止调用后续处理的函数
	cost := time.Since(start)
	fmt.Println("cost: ", cost)
}
func midFunc2(context *gin.Context) {
	fmt.Println("midFunc2中间件")
	context.Next() //调用后续处理的函数
    return //直接返回

}
func main() {
	r := gin.Default()
	r.Use(midFunc, midFunc2)
	{
		r.GET("/user", userFunc)
		r.GET("/index", indexFunc)
	} //规范代码

	r.Run(":9000")
}

局部

// 给/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!",
		})
	})

为路由组注册中间件

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

写法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) {...})
    ...
}

获取中间件里面的值

func indexFunc(context *gin.Context) {
	fmt.Println("indexFunc函数")
	name, ok := context.Get("name") //获取中间里面的值
	if !ok {
		name = "n"
	}
	fmt.Println(name)
	context.JSON(http.StatusOK, gin.H{
		"msg": "ok",
	})
}


func midFunc2(context *gin.Context) {
	context.Set("name", "zc") 
	fmt.Println("midFunc2中间件")
	context.Next() //调用后续处理的函数
}

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())。


func midFunc2(context *gin.Context) {
	context.Set("name", "zc") 
    go xx(context.Copy())
	fmt.Println("midFunc2中间件")
	context.Next() //调用后续处理的函数
}

同步异步

  • goroutine机制可以方便地实现异步处理
  • 另外,在启动新的goroutine时,不应该使用原始上下文,必须使用它的只读副本
package main

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

func main() {
   r := gin.New()
   // 1.异步
   r.GET("/long_async", func(c *gin.Context) {
      // 需要搞一个副本
      copyContext := c.Copy()
      // 异步处理
      go func() {
         time.Sleep(3 * time.Second)
         log.Println("异步执行:" + copyContext.Request.URL.Path)
      }()
      c.JSON(200,gin.H{"msg":"异步请求成功"})
   })
   // 2.同步
   r.GET("/long_sync", func(c *gin.Context) {
      time.Sleep(3 * time.Second)
      log.Println("同步执行:" + c.Request.URL.Path)
      c.JSON(200,gin.H{"msg":"同步请求成功"})
   })

   r.Run(":8000")
}
posted @ 2021-03-31 21:22  小子,你摊上事了  阅读(108)  评论(0)    收藏  举报