赞
踩
本篇博客从 接口超时middleware 的案例入手 深入剖析其原理
在项目根目录创建middleware 目录,然后在middleware目录创建time_out.go,代码如下
package middleware import ( "github.com/gin-gonic/gin" "golang.org/x/net/context" "net/http" "time" ) // TimeoutMiddleware 是一个用于设置超时时间的中间件 func TimeoutMiddleware(timeout time.Duration) gin.HandlerFunc { return func(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), timeout) defer cancel() c.Request = c.Request.WithContext(ctx) response := make(chan bool, 1) go func() { c.Next() response <- true }() select { case <-response: return case <-ctx.Done(): if ctx.Err() == context.DeadlineExceeded { c.JSON(http.StatusRequestTimeout, gin.H{"message": "Request timeout"}) c.Abort() return } } } }
然后更改/router/router.go代码,完整代码如下
package router import ( "ginWeb/handler" "ginWeb/middleware" "github.com/gin-gonic/gin" "time" ) func InitRoutes(app *handler.App) *gin.Engine { router := gin.New() root := router.Group("/gin-web") v1 := root.Group("v1") v1.Use(middleware.TimeoutMiddleware(time.Second * 5)) uaa := &uaa{app.Uaa} uaa.addRouter(v1) return router }
为了测试timeout 中间件是否有效,我们在login 接口 睡眠6s,/handler/uaa.go 完整代码如下
package handler import ( log "ginWeb/common/logger" "time" "golang.org/x/net/context" ) type UaaHandler interface { Login(ctx context.Context, req *LoginReq, rsp *LoginRsp) error } type uaa struct { } func newUaaHandler() UaaHandler { return &uaa{} } type LoginReq struct{} type LoginRsp struct { Id string `json:"id"` Name string `json:"name"` } func (u *uaa) Login(ctx context.Context, req *LoginReq, rsp *LoginRsp) error { log.Error("===========login==========start", nil) rsp.Id, rsp.Name = "1", "小明" time.Sleep(6 * time.Second) log.Error("===========login==========end", nil) return nil }
然后启动项目 打开终端在项目根目录 执行 go run main.go
执行 curl -XPOST http://127.0.0.1:8090/gin-web/v1/uaa/login ,会出现下面结果
{"message":"Request timeout"}
中间件的方法只需要定义为 func() gin.HandlerFunc {} 或
func(p inteface) gin.HandlerFunc {},方法的返回值 只能是 gin.HandlerFunc
看下面源码实现
type RouterGroup struct {
Handlers HandlersChain
basePath string
engine *Engine
root bool
}
type HandlersChain []HandlerFunc
var _ IRouter = (*RouterGroup)(nil)
// Use adds middleware to the group, see example code in GitHub.
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
group.Handlers = append(group.Handlers, middleware...)
return group.returnObj()
}
RouterGroup 结构体包括 Handlers 字段,该字段 为 HandlerFunc 切片 类型,和 中间件定义返回值相关,
*func (group RouterGroup) Use(middleware …HandlerFunc) IRoutes{} 方法 把 中间件定义的 返回值 追加到 Handlers 里边,因为是切片 所以这 一系列的中间件也是按照 Use 的顺序进行调用的。后续还有log、限流、auth等中间件讲解,下一篇博客我们使用gorm
进行数据读写操作
创作不易,喜欢的话请一键三连,转载请注明出处,侵权必究
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。