type ServeMux struct {
mu sync.RWMutex // 读写锁,保障哈希表的异步安全
m map[string]muxEntry // 路由器真身,其实是原生golang hash map
es []muxEntry // 路由器真身2号,用来实现前缀匹配
hosts bool // whether any patterns contain hostnames
}
type muxEntry struct {
explicit bool
h Handler
pattern string
}
// Most-specific (longest) pattern wins.
func (mux *ServeMux) match(path string) (h Handler, pattern string) {
v, ok := mux.m[path] // 直接从hash map中查entry是否存在
if ok {
return v.h, v.pattern
}
for _, e := range mux.es { // 遍历切片,找前缀
if strings.HasPrefix(path, e.pattern) {
return e.h, e.pattern
}
}
return nil, ""
}
type methodTree struct {
method string // http方法, 每种方法存一颗 radix tree 实例
root *node // 树的根节点
}
type node struct {
path string // 到该节点为止的path
children []*node // 子树
handlers HandlersChain // 处理该url的handlers数组
...
}
// 注册路由
func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
// gin里是每个方法一棵树,如 GET/POST/PUT 分别一棵
root := engine.trees.get(method)
if root == nil {
root = new(node)
root.fullPath = "/"
engine.trees = append(engine.trees, methodTree{method: method, root: root})
}
root.addRoute(path, handlers)
}