中间件
- 可以配置多个中间件
- 执行顺序类似 koa 的洋葱模型
例子1
- 路由中间件: 针对某个路由设置的中间件
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func initWare(c *gin.Context) {
fmt.Println("中间件1")
c.Next()
fmt.Println("中间件2")
}
func main() {
r := gin.Default()
//=> 可以配置多个中间件
r.GET("/home", initWare, func(c *gin.Context) {
c.String(200, "home")
})
r.Run()
}
例子2
- 全局中间件: 每个路由都需要先经过它
- 比如是否登录了鉴权
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func initWare1(c *gin.Context) {
fmt.Println("全局中间件1,每个路由都需要先经过它")
c.Next()
}
func initWare2(c *gin.Context) {
fmt.Println("全局中间件2,每个路由都需要先经过它")
c.Next()
}
func main() {
r := gin.Default()
//=> 可以配置多个中间件
r.Use(initWare1, initWare2)
r.GET("/home", func(c *gin.Context) {
c.String(200, "home")
})
r.Run()
}
例子3
- 路由分组中间件: 针对特定的路由集群设置的中间件
- 中间件的
设值
和控制器
的配合使用 - 中间件和中间件之间也是可以的
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func initWare1(c *gin.Context) {
fmt.Println("路由分组中间件1")
c.Set("username", "张三")//设置共享数据
c.Next()
}
func initWare2(c *gin.Context) {
fmt.Println("路由分组中间件2")
c.Next()
}
func main() {
r := gin.Default()
//=> 可以配置多个中间件 方式1
adminRouter := r.Group("/admin", initWare1, initWare2)
{
r.GET("/", func(c *gin.Context) {
c.String(200, "admin-home")
})
r.GET("/news", func(c *gin.Context) {
username, _ := c.Get("username")//获取数据
v, ok := username.(string)
if ok == true {
c.String(200, "admin-news-%v", username)
}else {
c.String(200, "获取页面失败")
}
})
}
frontRouter := r.Group("/front")
frontRouter.Use(initWare1, initWare2)//=> 方式二
{
r.GET("/", func(c *gin.Context) {
c.String(200, "admin-home")
})
r.GET("/news", func(c *gin.Context) {
c.String(200, "admin-news")
})
}
r.GET("/home", func(c *gin.Context) {
c.String(200, "home")
})
r.Run()
}
中间件的注意事项
gin默认中间件
- gin.Default()默认使用了 Logger 和 Recovery中间件
- Logger中间件将日志写入
gin.DefaultWriter
,即使配置了GIN_MODE=release - Recovery中间件会
recover
任何panic
.如果有 panic的话,会写入500响应码
- Logger中间件将日志写入
- 如果不想使用上面默认的中间件
- 可以使用
gin.New()
新建一个没有任何默认中间件的路由
- 可以使用
- gin中间件中使用 goroutine
- 当在中间件或handler中启动新的 goroutine时, 不能使用原始上下文
c *gin.Context
- 必须使用其只读副本(c.Copy())
- 当在中间件或handler中启动新的 goroutine时, 不能使用原始上下文
r.GET("/", func (c *gin.Context) {
cCp := c.Copy()
go func() {
time.Sleep(4 * time.Second)
// 创建副本
fmt.Println("do something" + cCp.Request.URL.Path)
}()
c.String(200, "这是首页")
})
就是你需要提前处理事务,或者分步骤去处理事务的时候,可以选择中间件