68 lines
1.5 KiB
Go
68 lines
1.5 KiB
Go
|
package nf
|
|||
|
|
|||
|
import "strings"
|
|||
|
|
|||
|
type node struct {
|
|||
|
pattern string // 待匹配路由,例如 /p/:lang
|
|||
|
part string // 路由中的一部分,例如 :lang
|
|||
|
children []*node // 子节点,例如 [doc, tutorial, intro]
|
|||
|
isWild bool // 是否精确匹配,part 含有 : 或 * 时为true
|
|||
|
}
|
|||
|
|
|||
|
// 第一个匹配成功的节点,用于插入
|
|||
|
func (n *node) matchChild(part string) *node {
|
|||
|
for _, child := range n.children {
|
|||
|
if child.part == part || child.isWild {
|
|||
|
return child
|
|||
|
}
|
|||
|
}
|
|||
|
return nil
|
|||
|
}
|
|||
|
|
|||
|
// 所有匹配成功的节点,用于查找
|
|||
|
func (n *node) matchChildren(part string) []*node {
|
|||
|
nodes := make([]*node, 0)
|
|||
|
for _, child := range n.children {
|
|||
|
if child.part == part || child.isWild {
|
|||
|
nodes = append(nodes, child)
|
|||
|
}
|
|||
|
}
|
|||
|
return nodes
|
|||
|
}
|
|||
|
|
|||
|
func (n *node) insert(pattern string, parts []string, height int) {
|
|||
|
if len(parts) == height {
|
|||
|
n.pattern = pattern
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
part := parts[height]
|
|||
|
child := n.matchChild(part)
|
|||
|
if child == nil {
|
|||
|
child = &node{part: part, isWild: part[0] == ':' || part[0] == '*'}
|
|||
|
n.children = append(n.children, child)
|
|||
|
}
|
|||
|
child.insert(pattern, parts, height+1)
|
|||
|
}
|
|||
|
|
|||
|
func (n *node) search(parts []string, height int) *node {
|
|||
|
if len(parts) == height || strings.HasPrefix(n.part, "*") {
|
|||
|
if n.pattern == "" {
|
|||
|
return nil
|
|||
|
}
|
|||
|
return n
|
|||
|
}
|
|||
|
|
|||
|
part := parts[height]
|
|||
|
children := n.matchChildren(part)
|
|||
|
|
|||
|
for _, child := range children {
|
|||
|
result := child.search(parts, height+1)
|
|||
|
if result != nil {
|
|||
|
return result
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return nil
|
|||
|
}
|