go-zero 单体应用框架学习—3 路由生成字典树

自己根据go-zero单体框架实现的一个精简版框架https://github.com/wanmei002/go-zero-learn, 新手直接看go-zero 框架可能会绕,看这个好理解

找到实现 http.Handler 接口的结构体

顺着入口函数 server.Start(),找到了 router.NewRouter() 创建的对象实现了 http.Handler 接口

创建的对象为 router.patRouter 结构体的实例

这个结构体有两个方法

  1. Handle 路由生成字典树
  2. ServeHTTP 方法实现了 http.Handler 接口,这个方法里有路由匹配,匹配失败的逻辑
type patRouter struct {
	trees      map[string]*search.Tree
	notFound   http.Handler
	notAllowed http.Handler
}

路由生成字典树

原理图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wqkjcnbo-1620886851260)(router-tree.png)]

生成字典树的主要代码,完整代码请看go-zero/rest/router/patrouter.go:

// Handle : 
// method : GET POST
// reqPath : ep: /home/article
// handler : 
func (pr *patRouter) Handle(method, reqPath string, handler http.Handler) error {
	if !validMethod(method) {
		return ErrInvalidMethod
	}

	if len(reqPath) == 0 || reqPath[0] != '/' {
		return ErrInvalidPath
	}
	
	fmt.Println("reqPath before:", reqPath)

	cleanPath := path.Clean(reqPath)
	fmt.Println("cleanPath:", cleanPath)
	tree, ok := pr.trees[method]
	if ok {
		err := tree.Add(cleanPath, handler)
		return err
	}

	tree = search.NewTree()
	pr.trees[method] = tree
	fmt.Printf("pr: %+v\n", pr)
	err := tree.Add(cleanPath, handler)
	fmt.Printf("tree : %+v\n", tree)
	return err
}

递归生成字典树:

func add(nd *node, route string, item interface{}) error {
	if len(route) == 0 {
		if nd.item != nil {
			return ErrDupItem
		}

		nd.item = item
		return nil
	}

	if route[0] == slash {
		return ErrDupSlash
	}

	for i := range route {
		if route[i] == slash {
			token := route[:i]
			children := nd.getChildren(token)
			if child, ok := children[token]; ok {
				if child != nil {
					return add(child, route[i+1:], item)
				}

				return ErrInvalidState
			}

			child := newNode(nil)
			children[token] = child
			return add(child, route[i+1:], item)
		}
	}

	children := nd.getChildren(route)
	if child, ok := children[route]; ok {
		if child.item != nil {
			return ErrDupItem
		}

		child.item = item
	} else {
		children[route] = newNode(item)
	}

	return nil
}

上一篇 : go-zero 单体应用框架学习—2 中间件的添加和原理

下一篇: go-zero 单体应用框架学习—4 监听端口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值