当前位置: 首页 > news >正文

企业网站开发百度小说排行榜

企业网站开发,百度小说排行榜,淘宝客cms建站教程,网站内容和备案不一样go web框架 gin-gonic源码解读03————middleware#xff08;context#xff09; 今天打完游戏有空整理整理之前看的gin的中间件设计#xff0c;go的中间件设计相较于前两站还是蛮简单#xff0c;蛮容易看懂的#xff0c;所以顺便把context也一起写一下。 中间件是现在w…go web框架 gin-gonic源码解读03————middlewarecontext 今天打完游戏有空整理整理之前看的gin的中间件设计go的中间件设计相较于前两站还是蛮简单蛮容易看懂的所以顺便把context也一起写一下。 中间件是现在web服务里统一化拓展最常用的功能他是为了在我们的web服务中实现一些可重复使用可组合的功能方法、可以让我们的 web逻辑在执行之前或者之后进行预处理后处理验证等操作。 在说中间件之前我们先回忆一下之前几张看过的代码的。 **gin.go** 文件中gin为了实现http.Handler接口而实现的ServeHTTP()方法 // ServeHTTP conforms to the http.Handler interface. func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {// 从对象池获取Context对象(对象池这里就不讲了大家可以搜博客去看这里只要大家会用就可以了)c : engine.pool.Get().(*Context)// 这三行其实就context的构造传入http.ResponseWriter,*http.Requestc.writermem.reset(w)c.Request reqc.reset()// 去我们的路由中查找响应的url并执行响应的逻辑engine.handleHTTPRequest(c)engine.pool.Put(c) } 这里再顺便给大家介绍一下contextcontext实际上就是gin框架为了统一的参数管理包装的数据结构他除了包含了我们每次访问ServeHTTP的传参(w http.ResponseWriter, req *http.Request)还包含了一些封装的web Response方法调用就返回非常好用和一些请求获取参数的方法其基本上覆盖了开发者平时所以操作需求有兴趣的同学可以自己看看 .\Go\gin\context.go 中的内容。 // 这里缩略一下只讲今天会用到的几个参数 type Context struct {writermem responseWriterRequest *http.RequestWriter ResponseWriterhandlers HandlersChain // 中间件执行链handlers index int8 // 执行下标fullPath string// 引擎的指针engine *Engine略 }我们回到正题看看我们的**handleHTTPRequest()**方法 // 去我们的路由中查找响应的url并执行响应的逻辑 engine.handleHTTPRequest( c ) 这就是我们上次手撕的那个前缀树的查找方法。而我们的目的是通过收到http请求的url来找到客户端需要请求的逻辑接口。 // 由于篇幅所限代码会有所缩略func (engine *Engine) handleHTTPRequest(c *Context) {// 很显然就是把我们请求方法和路径从Context里拿出来方便使用httpMethod : c.Request.MethodrPath : c.Request.URL.Pathunescape : false略// Find root of the tree for the given HTTP method// 这里就是我们的前缀树的t : engine.treesfor i, tl : 0, len(t); i tl; i {// 这里前面说过的引擎(engine)中存的是一个前缀树的切片([]tree)// 每个请求方法一棵树这里是遍历切片找到对应的请求方法if t[i].method ! httpMethod {continue}root : t[i].root// Find route in tree// 找到树了去树里查找value : root.getValue(rPath, c.params, c.skippedNodes, unescape)// 参数节点拿参数if value.params ! nil {c.Params *value.params}// 关键点来了这里就找到了我们要执行的逻辑方法if value.handlers ! nil {c.handlers value.handlersc.fullPath value.fullPathc.Next()c.writermem.WriteHeaderNow()return}略}break}略serveError(c, http.StatusNotFound, default404Body) }为了讲的详细的点我们把我们的关键代码单独拿出来说 c.handlers value.handlers // 1.将接口的handlers赋值给了Context的handlersc.fullPath value.fullPath // 2.给fullPath 赋值c.Next() // 3.执行Next() 方法c.writermem.WriteHeaderNow()// 4. 给HTTP response写入status codereturn步骤1的赋值给的是handlers 而不是handler这里大家可能会很奇怪我业务逻辑其实一个函数就可以解决这里为啥会缓存一个handlers呢难道我的业务函数要拆分成好几个函数来写其实这个handlers 存储的除了我们业务函数就是我们所有的中间件函数。 // HandlerFunc defines the handler used by gin middleware as return value. type HandlerFunc func(*Context)// HandlersChain defines a HandlerFunc slice. type HandlersChain []HandlerFuncgin的中间件调用的密码也都包含在步骤3里 func (c *Context) Next() {// 执行下标c.index// 一上来就自增是因为func (c *Context) reset()这个初始化方法里会把下标初始化成-1所以我们一上来就要让他变成0。// 这么做的目的就是因为我们的中间件函数中也会调用Next()for c.index int8(len(c.handlers)) {// 通过下标去执行中间件c.handlers[c.index](c)// 显然执行完了,不然就死循环了c.index} }gin的中间件调用的秘密还是蛮简单的接下来我们看看gin中间件的注册。 gin的中间件注册大家都知道engine可以使用Use路由组的RouterGroup也可以使用Use实际上engine.Use()也是调用了RouterGroup.Use(),因为我们engine的路由包括了我们所有的RouterGroup的路由。 func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {engine.RouterGroup.Use(middleware...)// 这边是初始化的时候顺便注册一些异常的处理方式// 当然为了避免重复的调用这两个rebuild40X函数这个Use还是建议一次性调用到位engine.rebuild404Handlers() engine.rebuild405Handlers()return engine }// Use adds middleware to the group, see example code in GitHub. func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {// 非常的简单我们的Handlers 是一个切片他把所有的middleware插入到中间件的末端group.Handlers append(group.Handlers, middleware...)return group.returnObj() }这样子就实现了我们功能强大的中间件调用链条只说这些感觉内容少了点再带大家看看gin自带的两个中间件把。 // 这是gin代码中获取默认Engine 的方法大家一定都用过 func Default() *Engine {// 无关紧要的版本校验debugPrintWARNINGDefault()// New()第一篇应该说过engine : New()// 这里调用了两个中间件Logger(), Recovery()engine.Use(Logger(), Recovery())return engine }Logger() 顾名思义很显然是打印日志的一个中间件打印日志也是中间件在开发中最有用的几个用处之一 func Logger() HandlerFunc {return LoggerWithConfig(LoggerConfig{}) }// LoggerWithConfig instance a Logger middleware with config. func LoggerWithConfig(conf LoggerConfig) HandlerFunc {// LoggerConfig不是我们本文讲解的重点大家可以自己去看看// 这下面的代码大意就是获取日志的打印格式和输出位置formatter : conf.Formatterif formatter nil {formatter defaultLogFormatter}out : conf.Outputif out nil {out DefaultWriter}notlogged : conf.SkipPathsisTerm : trueif w, ok : out.(*os.File); !ok || os.Getenv(TERM) dumb ||(!isatty.IsTerminal(w.Fd()) !isatty.IsCygwinTerminal(w.Fd())) {isTerm false}// 知识点struct{}不占内存空间// 在go语言map[string]struct{}的写法相当于创建了一个set结构体。var skip map[string]struct{}if length : len(notlogged); length 0 {skip make(map[string]struct{}, length)for _, path : range notlogged {skip[path] struct{}{}}}// 正文开始return func(c *Context) {// Start timerstart : time.Now()path : c.Request.URL.Pathraw : c.Request.URL.RawQuery// Process request// 可能很多人会好奇为什么在中间件的中间还要执行一个next// 这是一个中间件在逻辑函数执行之前还有逻辑函数执行之后都有钩子逻辑可以执行// 大家可以把这个想象成一个套娃的结构// 例如logger() 前半段logic() 业务逻辑代码logger() 后半段c.Next()// Log only when path is not being skipped// 上面英文很简单大家自己看看if _, ok : skip[path]; !ok {param : LogFormatterParams{Request: c.Request,isTerm: isTerm,Keys: c.Keys,}// Stop timer// 结构化打印然后输出到流中没啥好说的param.TimeStamp time.Now()param.Latency param.TimeStamp.Sub(start)param.ClientIP c.ClientIP()param.Method c.Request.Methodparam.StatusCode c.Writer.Status()param.ErrorMessage c.Errors.ByType(ErrorTypePrivate).String()param.BodySize c.Writer.Size()if raw ! {path path ? raw}param.Path path// 输出完了fmt.Fprint(out, formatter(param))}} } 不过一般大家的项目之中都不会用gin提供的logger中间件因为大家都有自己的日志格式不过你实在想用也可以把自己的logger实例实现gin.logger的接口然后在初始化engine的时候传给engine就好了 完
http://www.hkea.cn/news/14304820/

相关文章:

  • 网站建设可行性研究提供五屏网站建设
  • 网站开发环境lmnp绑定手机网站文件夹
  • 建设360导航网站的目的是什么意思wordpress需要做哪些设置
  • 新郑市网站建设小程百度最贵关键词排名
  • 网站建设具体详细过程wordpress积分推广插件
  • dw网页设计模板网站李守洪排名大师怎么样
  • 东莞网站设计定制开发西安网站设计报价
  • 网站安装百度商桥竣工验收报告查询网
  • 如何对网站进行维护烟台牟平住房建设局网站
  • 那家建网站宝盒好用门户网站的类型
  • asp.net 网站修改发布中企网络科技建站
  • 怎么组建企业网站wordpress修改宽度
  • 浙江手机网站建设国外网站欣赏
  • 公司建立网站的好处有没有IT做兼职的网站
  • 建设门户网站的目的网站中文域名怎么做
  • 国内网站开发平台哪家强旅游网站开发指导
  • 寻找常州微信网站建设wordpress保存为模板
  • 首钢水钢赛德建设有限公司网站同仁seo排名优化培训
  • 车子网站软件开发过程包括
  • 阿里云备案网站服务内容怎么填电子商务网站建设自服务器
  • 专业房地产网站建设网站设计超链接怎么做
  • 韩国网站后缀php网站开发学什么
  • 百度打网站名称就显示 如何做大连建站免费模板
  • 呼和浩特住房和城乡建设部网站房九九西安房产网
  • 帝国cms网站建设深圳出行最新消息
  • iis怎么使用来建设一个网站软件项目外包网
  • 网站301在哪里做怎么用网页制作一个网站
  • 彩票网站该怎么建设网站建设外包项目
  • 做品牌特价的网站有哪些推广引流方案
  • 很多网站没排名了宝应县城乡建设局网站