Gin 路由添加流程

简介: Gin 路由添加流程
  1. 计算 absolutePath
  2. 业务 HandlerFunc 与中间件 HandlerFunc 组合
  3. Engine methodTrees 添加路由
  • methodTrees 实际上是 methodTree 组成的森林,每个 methodTree 是一颗 HTTP 方法的树
  • Engine.addRoute
func (engine *Engine) addRoute(method, path string, handlers HandlersChain) { assert1(path[0] == '/', "path must begin with '/'") assert1(method != "", "HTTP method can not be empty") assert1(len(handlers) > 0, "there must be at least one handler")
  debugPrintRoute(method, path, handlers)
  root := engine.trees.get(method)//是否有HTTP方法的路由树 if root == nil {//没有 构建根节点    root = new(node)    root.fullPath = "/"   engine.trees = append(engine.trees, methodTree{method: method, root: root}) } root.addRoute(path, handlers)
  // Update maxParams if paramsCount := countParams(path); paramsCount > engine.maxParams {   engine.maxParams = paramsCount  }
  if sectionsCount := countSections(path); sectionsCount > engine.maxSections {   engine.maxSections = sectionsCount  }}


  • node.addRoute
func (n *node) addRoute(path string, handlers HandlersChain) {  fullPath := path  n.priority++
  // Empty tree if len(n.path) == 0 && len(n.children) == 0 {   n.insertChild(path, fullPath, handlers)   n.nType = root    return  }
  parentFullPathIndex := 0
walk: for {   // Find the longest common prefix.    // This also implies that the common prefix contains no ':' or '*'    // since the existing key can't contain those chars.    i := longestCommonPrefix(path, n.path)
    // Split edge   if i < len(n.path) {      child := node{        path:      n.path[i:],        wildChild: n.wildChild,       indices:   n.indices,       children:  n.children,        handlers:  n.handlers,        priority:  n.priority - 1,        fullPath:  n.fullPath,      }
      n.children = []*node{&child}      // []byte for proper unicode char conversion, see #65     n.indices = bytesconv.BytesToString([]byte{n.path[i]})      n.path = path[:i]     n.handlers = nil      n.wildChild = false     n.fullPath = fullPath[:parentFullPathIndex+i]   }
    // Make new node a child of this node   if i < len(path) {      path = path[i:]     c := path[0]
      // '/' after param      if n.nType == param && c == '/' && len(n.children) == 1 {       parentFullPathIndex += len(n.path)        n = n.children[0]       n.priority++        continue walk     }
      // Check if a child with the next path byte exists      for i, max := 0, len(n.indices); i < max; i++ {       if c == n.indices[i] {          parentFullPathIndex += len(n.path)          i = n.incrementChildPrio(i)         n = n.children[i]         continue walk       }     }
      // Otherwise insert it      if c != ':' && c != '*' && n.nType != catchAll {        // []byte for proper unicode char conversion, see #65       n.indices += bytesconv.BytesToString([]byte{c})       child := &node{         fullPath: fullPath,       }       n.addChild(child)       n.incrementChildPrio(len(n.indices) - 1)        n = child     } else if n.wildChild {       // inserting a wildcard node, need to check if it conflicts with the existing wildcard        n = n.children[len(n.children)-1]       n.priority++
        // Check if the wildcard matches        if len(path) >= len(n.path) && n.path == path[:len(n.path)] &&          // Adding a child to a catchAll is not possible         n.nType != catchAll &&          // Check for longer wildcard, e.g. :name and :names         (len(n.path) >= len(path) || path[len(n.path)] == '/') {          continue walk       }
        // Wildcard conflict        pathSeg := path       if n.nType != catchAll {          pathSeg = strings.SplitN(pathSeg, "/", 2)[0]        }       prefix := fullPath[:strings.Index(fullPath, pathSeg)] + n.path        panic("'" + pathSeg +         "' in new path '" + fullPath +          "' conflicts with existing wildcard '" + n.path +         "' in existing prefix '" + prefix +         "'")      }
      n.insertChild(path, fullPath, handlers)     return    }
    // Otherwise add handle to current node   if n.handlers != nil {      panic("handlers are already registered for path '" + fullPath + "'")    }   n.handlers = handlers   n.fullPath = fullPath   return  }}



目录
相关文章
|
9月前
|
存储 中间件 测试技术
gin 路由注册源码分析
Gin 是一个用 Go (Golang) 编写的 HTTP Web 框架。 它具有类似 Martini 的 API,但性能比 Martini 快 40 倍。如果你需要极好的性能,使用 Gin 吧。
Yii2.0框架中如何进行路由设置?它支持哪些路由规则?
Yii2.0框架中如何进行路由设置?它支持哪些路由规则?
343 0
|
15天前
|
缓存 网络协议 搜索推荐
gin框架学习笔记(三) ——路由请求与相关参数
gin框架学习笔记(三) ——路由请求与相关参数
|
15天前
|
JSON 中间件 数据格式
Gin框架学习笔记(五) ——文件上传与路由中间件
Gin框架学习笔记(五) ——文件上传与路由中间件
|
2月前
|
缓存 JavaScript 中间件
除了Gin和Iris,还有哪些其他的框架支持路由参数?
除了Gin和Iris,还有哪些其他的框架支持路由参数?
21 3
|
2月前
Koa2 如何处理路由?
Koa2 如何处理路由?
15 0
|
11月前
|
缓存
umi如何做一个路由的鉴权?
在wrappers文件夹创建一个index.tsx文件夹
201 0
|
12月前
|
中间件 Go API
Gin框架的路由解析与示例
本文将详细分析Gin框架的路由实现原理,并提供简单的代码示例以及运行结果。我们将通过深入探讨Gin框架的设计和代码结构,解释其背后的路由机制,并讨论如何使用Gin实现灵活的路由功能。
228 1
|
12月前
|
中间件 API Go
Gin增加超时控制中间件
Gin增加超时控制中间件
|
存储 算法 搜索推荐
Go Gin web框架的路由原理及中间件原理
Go Gin web框架的路由原理及中间件原理
554 0
Go Gin web框架的路由原理及中间件原理

热门文章

最新文章