framework1/framework/Tree.go

148 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package framework
import (
"errors"
"strings"
)
type Tree struct {
root *node // 根节点
}
func NewTree() *Tree {
root := newNode()
return &Tree{root}
}
type node struct {
isLast bool // 代表这个节点是否可以成为最终的路由规则。该节点是否能成为一个独立的uri, 是否自身就是一个终极节点
segment string // uri中的字符串代表这个节点表示的路由中某个段的字符串
handler ControllerHandler // 代表这个节点中包含的控制器,用于最终加载调用
children []*node // 代表这个节点下的子节点
}
func newNode() *node {
return &node{
isLast: false,
segment: "",
children: []*node{},
}
}
func isWildSegment(segment string) bool {
return strings.HasPrefix(segment, ":")
}
func (n *node) filterChildNodes(segment string) []*node {
if len(n.children) == 0 {
return nil
}
if isWildSegment(segment) {
return n.children
}
nodes := make([]*node, 0, len(n.children))
for _, child := range n.children {
if isWildSegment(child.segment) {
nodes = append(nodes, child)
} else if child.segment == segment {
nodes = append(nodes, child)
}
}
return nodes
}
func (n *node) matchNode(uri string) *node {
segments := strings.SplitN(uri, "/", 2) // 使用分隔符将uri切割为两个部分
segment := segments[0] // 第一个部分用于匹配下一层子节点
if segment == "" {
return n.matchNode(segments[1])
}
if !isWildSegment(segment) {
segment = strings.ToUpper(segment)
}
children := n.filterChildNodes(segment) // 匹配符合的下一层子节点
if children == nil || len(children) == 0 {
return nil
}
if len(segments) == 1 {
// 如果segment已经是最后一个节点判断这些children是否有isLast标志
for _, tn := range children {
if tn.isLast {
return tn
}
}
return nil
}
// 如果有2个segment, 递归每个子节点继续进行查找
for _, child := range children {
tnMatch := child.matchNode(segments[1])
if tnMatch != nil {
return tnMatch
}
}
return nil
}
func (tree *Tree) AddRouter(uri string, handler ControllerHandler) error {
n := tree.root
// 确认路由是否冲突
if n.matchNode(uri) != nil {
return errors.New("route exist: " + uri)
}
segments := strings.Split(uri, "/")
for index, segment := range segments {
if segment == "" {
continue
}
if !isWildSegment(segment) {
segment = strings.ToUpper(segment)
}
isLast := index == len(segments)-1
var objNode *node // 标记是否有合适的子节点
children := n.filterChildNodes(segment)
if len(children) > 0 {
// 如果有segment相同的子节点则选择这个子节点
for _, child := range children {
if child.segment == segment {
objNode = child
break
}
}
}
//如果没有找到合适的子节点就要创建一个新节点
if objNode == nil {
child := &node{}
child.segment = segment
if isLast {
child.isLast = true
child.handler = handler
}
n.children = append(n.children, child)
objNode = child
}
n = objNode
}
return nil
}
func (tree *Tree) FindHandler(uri string) ControllerHandler {
match := tree.root.matchNode(uri)
if match == nil {
return nil
}
return match.handler
}