手把手和你一起实现一个Web框架实战——EzWeb框架(五)[Go语言笔记]Go项目实战
2021/8/20 23:05:52
本文主要是介绍手把手和你一起实现一个Web框架实战——EzWeb框架(五)[Go语言笔记]Go项目实战,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
手把手和你一起实现一个Web框架实战——EzWeb框架(五)[Go语言笔记]Go项目实战
代码仓库:
github
gitee
中文注释,非常详尽,可以配合食用
本篇代码,请选择demo5
中间件实现
一、Context设计
type Context struct { Writer http.ResponseWriter Req *http.Request //请求的信息,包括路由和方法 Path string Method string Params map[string]string /*用于存储外面拿到的参数 ":xxx" or "*xxx" */ //响应的状态码 StatusCode int //中间件 handlers []HandlerFunc index int /* 用于记录当前执行到第几个中间件 */ }
我们每次请求生成的context,我们选择在其中放入和我们中间件和执行控制变量index
二、中间件对路由组的注册方法
// 将路中间件,放入路由组的中间件方法切片中 func (group *RouterGroup) Use(middlewares ...HandlerFunc) { group.middlewares = append(group.middlewares, middlewares...) }
当每个请求到来后,ServeHTTP函数执行时,它将该生成一个context并将进行传入的url和路由组前缀做前缀对比,找到满足条件的路由组,取出它的中间件,然后存入到生成的context。
// ServeHTTP 方法的实现,用于实现处理HTTP请求 func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { var middlewares []HandlerFunc for _, group := range engine.groups { //比对路由组存的前缀和请求路径,把属于这个请求映射的路由组中的中间件取到 //意思就是比对发现该请求属于哪一个路由组,需要哪些中间件,取出来执行 if strings.HasPrefix(req.URL.Path, group.prefix) { middlewares = append(middlewares, group.middlewares...) } } //根据req和w实例一个context c := newContext(w, req) //将取道的中间件赋给这个context c.handlers = middlewares //通过封装好的context执行处理 engine.router.handle(c) }
三、处理函数
在处理函数handle()中,我们根据路由拿到已经注册的方法,放入到中间件后,在通过Next函数进行处理
//根据context中存储的 c.Method 和 c.Path 拿到对应的处理方法,进行执行,如果拿到的路由没有注册,则返回404 func (r *router) handle(c *Context) { //获取匹配到的节点,同时也拿到两类动态路由中参数 n, params := r.getRoute(c.Method, c.Path) if n != nil { c.Params = params //拿目的节点中的path做key来找handlers key := c.Method + "-" + n.path //根据路径拿到处理器 c.handlers = append(c.handlers, r.handlers[key]) }else { //不存在节点的情况下,给生成的c加入一个404方法 c.handlers = append(c.handlers, func(c *Context) { c.String(http.StatusNotFound, "404 NOT FOUND: ", c.Path) }) } c.Next() }
四、Next方法执行处理
index进行控制,遍历完c.handlers中存储的方法执行。
// 当中间件调用了 Next 方法时,就往后执行下一个,同时index交由下一个中间件控制 func (c *Context) Next() { c.index++ //执行完之后所有的handlers for ;c.index < len(c.handlers); c.index++{ c.handlers[c.index](c) } }
这里的日志中间件在Next中被执行时,也调用了Next函数。这里第四行的执行巧妙的做到了,控制index++,执行下一个中间件,直到执行完了又回到Logger执行,回到原来的Next的for循环,发现不满足继续循环的条件,然后退出。
func Logger() HandlerFunc { return func(c *Context) { t := time.Now() c.Next() log.Printf("[%d] %s in %v", c.StatusCode, c.Req.RequestURI, time.Since(t)) } }
demo测试:
/* @Time : 2021/8/16 下午4:01 @Author : mrxuexi @File : main @Software: GoLand */ package main import ( "Ez" "net/http" ) func main() { r := Ez.New() //给所有的路由组都添加了中间件logger r.Use(Ez.Logger()) api := r.Group("/api") api.POST("/hello", func(c *Ez.Context) { c.JSON(http.StatusOK,Ez.H{ "message" : "hello", }) }) //next的应用 api.Use(func(c *Ez.Context) { c.JSON(200,Ez.H{ "test" : "middleware2-1", }) c.Next() c.JSON(200, Ez.H{ "test" : "middleware2-2", }) }) r.Run(":9090") }
成功!
参考:
[1]: https://github.com/geektutu/7days-golang/tree/master/gee-web ""gee""
[2]: https://github.com/gin-gonic/gin ""gin""
这篇关于手把手和你一起实现一个Web框架实战——EzWeb框架(五)[Go语言笔记]Go项目实战的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15SendGrid 的 Go 客户端库怎么实现同时向多个邮箱发送邮件?-icode9专业技术文章分享
- 2024-11-15SendGrid 的 Go 客户端库怎么设置header 和 标签tag 呢?-icode9专业技术文章分享
- 2024-11-12Cargo deny安装指路
- 2024-11-02MongoDB项目实战:从入门到初级应用
- 2024-11-01随时随地一键转录,Google Cloud 新模型 Chirp 2 让语音识别更上一层楼
- 2024-10-25Google Cloud动手实验详解:如何在Cloud Run上开发无服务器应用
- 2024-10-24AI ?先驱齐聚 BAAI 2024,发布大规模语言、多模态、具身、生物计算以及 FlagOpen 2.0 等 AI 模型创新成果。
- 2024-10-20goland工具下,如修改一个项目的标准库SDK的版本-icode9专业技术文章分享
- 2024-10-17Go学习:初学者的简单教程
- 2024-10-17Go学习:新手入门完全指南