首页 >> 职场 >> gin框架(三)gin 路由的付诸剖析

gin框架(三)gin 路由的付诸剖析

2024-12-31 职场

ethod 法则时,去 trees slice 中都遍历如果 trees slice 依赖于这个 method, 则这个URL近似于的 handler 反之亦然移除到寻找的数据流竹子上如果没寻找,则之后创始人一颗新的法则竹子出来, 然后将 URL近似于的 handler 移除到这个数据流 竹子上gin 数据流的申请人操作过程func main() { r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run() // listen and serve on 0.0.0.0:8080}解码标识符

这段直观的标识符中都都,r.Get 就申请人了一个数据流 /ping 转入 GET tree 中都。这是最普通的,也是最类似于的申请人方式为。

不过上就会这种撰写法,一般都是用来测试的,正常状况下我们就会将 handler 到手 Controller 层进去去,申请人数据流放置专门的 route 管理者进去,这中都都就不日后简要扩大,等后面具体话说下 gin 的架构自上而下新设计。

//controller/somePost.gofunc SomePostFunc(ctx *gin.Context) { // do something context.String(http.StatusOK, "some post done")}解码标识符MLT-MLT-MLT-go// route.gorouter.POST("/somePost", controller.SomePostFunc)解码标识符使用 RouteGroupv1 := router.Group("v1"){ v1.POST("login", func(context *gin.Context) { context.String(http.StatusOK, "v1 login") })}解码标识符

RouteGroup 是相当重要的基本功能,举个举例来说:一个零碎的 server 服务,url 并不需要分为鉴权适配器和非鉴权适配器,就可以使用 RouteGroup 来借助。回事最类似于的,还是用来近似于适配器的版本升级。这些操作, 事与愿违都就会在自由基到gin的数据流竹子上

gin 数据流的具体借助func main() { r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run() // listen and serve on 0.0.0.0:8080}解码标识符

还是从这个直观的举例来说应从。我们只并不需要弄清楚示例三个缺陷均可:

URL->ping 放置哪中都都了?handler-> 放置哪中都都了?URL 和 handler 是如何关联慢慢地的?1. GET/POST/DELETE/..的事与愿违归宿func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle(http.MethodGet, relativePath, handlers)}解码标识符

在调用POST, GET, HEAD等数据流HTTP相关表达式时, 就会调用handle表达式。handle 是 gin 数据流的统一大门。

// routergroup.go:L72-77func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes { absolutePath := group.calculateAbsolutePath(relativePath) handlers = group.combineHandlers(handlers) group.engine.addRoute(httpMethod, absolutePath, handlers) return group.returnObj()}解码标识符2. 生成数据流竹子

示例考虑一个状况,论点有示例这样的数据流,你就会怎么新设计这棵数据流竹子?

GET /abc GET /abdGET /af解码标识符

当然最直观最行径的就是每个URL租用一个竹子的嫩叶端口,不过这种新设计就会带给的缺陷:

租用内存就会下降时,我们看不到 abc, abd, af 都是用共同的词组的,如果能共用词组的话,是可以省内存空间的

gin 数据流竹子是一棵词组竹子. 我们前面话说过 gin 的每种法则(POST, GET ...)都有自己的一颗竹子,当然这个是根据你申请人数据流来的,并不是一上来把每种方式为都申请人一遍。gin 每棵数据流约莫是示例的样子

这个流程的标识符太多,这中都都就不日后黏贴出具体标识符中都都,热衷于的同学可以按照这个思路看下去均可。

3. handler 与 URL 关联type node struct { path string indices string wildChild bool nType nodeType priority uint32 children []*node // child nodes, at most 1 :param style node at the end of the array handlers HandlersChain fullPath string}解码标识符

node 是数据流竹子的整体结构

children 就是一颗竹子的嫩叶结点。每个数据流的换成词组后,都被原产在这些 children 数组中都都path 就是局限性嫩叶端口的最长的词组handlers 进去放于的就是局限性嫩叶端口近似于的数据流的处理表达式当寄出客户侧劝告时,如何寻找近似于的数据流的handler?

《gin 程式码阅读(2) - http劝告是如何注入gin的?》第二篇话说到 net/http 相当重要的表达式 ServeHTTP,当 server 寄出劝告时,必然就会前行到这个表达式中都都。由于 gin 借助这个 ServeHTTP,所以输水就转入 gin 的逻辑进去。

// gin.go:L439-443func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { c := engine.pool.Get().(*Context) c.writermem.reset(w) c.Request = req c.reset() engine.handleHTTPRequest(c) engine.pool.Put(c)}解码标识符

所以,当 gin 寄出客户侧的劝告时, 第一件事就是去数据流竹子进去去归一化近似于的 URL,寻找相关的数据流, 到手相关的处理表达式。回事这个操作过程就是 handleHTTPRequest 要干的一定会。

func (engine *Engine) handleHTTPRequest(c *Context) { // ... t := engine.trees for i, tl := 0, len(t); i < tl; i++ { if t[i].method != httpMethod { continue } root := t[i].root // Find route in tree value := root.getValue(rPath, c.params, unescape) if value.params != nil { c.Params = *value.params } if value.handlers != nil { c.handlers = value.handlers c.fullPath = value.fullPath c.Next() c.writermem.WriteHeaderNow() return } if httpMethod != "CONNECT" && rPath != "/" { if value.tsr && engine.RedirectTrailingSlash { redirectTrailingSlash(c) return } if engine.RedirectFixedPath && redirectFixedPath(c, root, engine.RedirectFixedPath) { return } } break } // ...}解码标识符

从标识符上看这个操作过程回事也很直观:

遍历所有的数据流竹子,寻找近似于的法则的那棵竹子归一化近似于的数据流寻找近似于的 handler。

长春治白癜风哪里最好
普洱白癜风医院哪家好
池州哪家白癜风医院好
新冠特效药
艾得辛和来氟米特的区别是什么
治疗新冠的药有哪些
痛风吃英太青和布洛芬哪个好
月经量多
TAG:路由框架
友情链接