通过上一篇的学习笔记,咱们已经知道了Gin router的主要流程。可是咱们看到代码和方法体整体很长,其中大部分是参数路由的判断。这些零散的小逻辑,让咱们阅读源码的时候更难理解了一些。可是其实基数树的逻辑兵没有这么的复杂,因此咱们仍是按照老规矩,本身实现如下这个简单的基数树值包含主流程。代码以下:node
package mygin import "fmt" type Trees map[string]*node type node struct { path string indices string children []*node handlers HandlerList } func (n *node) addRoute(path string, handlers HandlerList) { if len(n.path) > 0 || len(n.children) > 0 { walk: for { //找到相等的index i := 0 max := min(len(path), len(n.path)) for max > i && path[i] == n.path[i] { i++ } //须要把原来的做为子node放到新node中 if i < len(n.path) { //新建node child := node{ path: n.path[i:], indices: n.indices, handlers: n.handlers, children: n.children, } n.children = []*node{&child} n.indices = string([]byte{n.path[i]}) n.path = path[:i] n.handlers = nil } // 判断子节点若是有相同开头的字符 则重新跳入循环 if i < len(path) { c := path[i] for index := 0; index < len(n.indices); index++ { if c == n.indices[index] { n = n.children[index] path = path[i:] continue walk } } //把新请求的path加入到router中 n.insertChild(path[i:], path, handlers, i) return } return } } else { //若是为空 n.path = path n.handlers = handlers } } func (n *node) insertChild(path, fullPath string, handlers HandlerList, index int) { child := node{} child.handlers = handlers child.indices = "" child.path = path n.indices += string([]byte{fullPath[index]}) n.children = append(n.children, &child) } func min(a, b int) int { if a > b { return b } return a } func (n *node) getValue(path string) (handlers HandlerList) { index := 1 walk: for { fmt.Println("loop num: ", index) if len(path) > len(n.path) { path = path[len(n.path):] c := path[0] for i := 0; i < len(n.indices); i++ { if c == n.indices[i] { n = n.children[i] index++ goto walk } } } else if len(path) == len(n.path) { handlers = n.handlers return } } }
上面的代码已经不须要太多的注释了,去掉了参数节点的代码整个流程已经很明确了。app
Gin的源码学习和分析已经所有结束了。其实对于Gin框架源码的分析已经有了不少文章,可是若是在学习的同时本身也简单的模仿和实现一下这些功能对于咱们理解就更有帮助。
Gin是一个十分轻巧http框架,代码也十分的简介和清楚。实现也有一些亮点,我以为很适合新手对于go源码学习和分析的入门框架。但愿这5篇文章能对在学习go中的人有一些帮助。框架