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

网站后台管理系统怎么进seo个人优化方案案例

网站后台管理系统怎么进,seo个人优化方案案例,怎么做代刷网网站app,网站开发需要哪些技能go web框架 gin-gonic源码解读03————middleware(context) 今天打完游戏有空整理整理之前看的gin的中间件设计,go的中间件设计相较于前两站还是蛮简单,蛮容易看懂的,所以顺便把context也一起写一下。 中间件是现在w…

go web框架 gin-gonic源码解读03————middleware(context)


今天打完游戏有空整理整理之前看的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)
}

这里再顺便给大家介绍一下context,context实际上就是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 []HandlerFunc

gin的中间件调用的密码也都包含在步骤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.tj-hxxt.cn/news/34555.html

相关文章:

  • 网站制作案例图片山东百度推广总代理
  • 建立网站有什么好处兰州seo技术优化排名公司
  • 2017织梦网站怎么做seo祁阳seo
  • 大连网站建设那家好百度推广客服电话
  • 网站聊天室怎样做炫彩马甲企业网络推广软件
  • 如何修改网站濮阳市网站建设
  • 国内个人网站欣赏百度网站登录入口
  • 网站开发计什么科目5188关键词挖掘工具
  • 小程序开发公司介绍seo全网图文推广
  • wordpress 南非政府百度关键词怎么优化
  • 创建网站代码是什么问题北京核心词优化市场
  • 网站排名优化谷歌首页
  • 网站还没有做解析是什么意思网上售卖平台有哪些
  • 廊坊网站建设方案策划百度知道下载安装
  • 有没有帮人做CAD的网站杭州seo公司排名
  • 在线视频网站怎么做中国联通腾讯
  • 政府门户网站建设要求互联网广告推广
  • 做网站实现图片自动压缩百度分析工具
  • 温州人才网站开发百度收录要多久
  • 做网站能用自己电脑吗杭州seo网站哪家好
  • 网站运营推广公司中国疫情最新情况
  • 做自己的网站发表文章后怎么能让钱赚到手是不是点击率高就可以有收入?请高人指教!感激涕零!域名申请
  • 如何做印刷报价网站网站建设制作
  • 福建省住建厅建设网站企业网络推广方案策划书
  • 做电商网站需要会些什么问题徐州seo公司
  • 做理财的网站有哪些内容网络营销的认识与理解
  • 网营中国网站建设河南制作网站
  • 黑白灰网站外贸推广平台哪家好
  • 网站程序定制seo入门教程视频
  • 永久免费wap建站环球资源外贸平台免费