中间件
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()默认使用了Logger和Recovery中间件,其中:
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")
}

浙公网安备 33010602011771号