子 /api/:user
,如果是 api
,没有以 :
开头,那就不会走 if
逻辑。
接下来匹配 :user
部分,如果实际请求的 url 是 /api/zhangsan
,那么会将 user
作为 key
,zhangsan
作为 value
保存到结果中。
下面是搜索查找代码:
// Search searches item that associates with given route.
func (t *Tree) Search(route string) (Result, bool) {
// 第一步先判断是不是 / 开头
if len(route) == 0 || route[0] != slash {
return NotFound, false
}
var result Result
ok := t.next(t.root, route[1:], &result)
return result, ok
}
func (t *Tree) next(n *node, route string, result *Result) bool {
if len(route) == 0 && n.item != nil {
result.Item = n.item
return true
}
for i := range route {
// 和 add 里同样的提取逻辑
if route[i] != slash {
continue
}
token := route[:i]
return n.forEach(func(k string, v *node) bool {
r := match(k, token)
if !r.found || !t.next(v, route[i+1:], result) {
return false
}
// 如果 url 中有参数,会把键值对保存到结果中
if r.named {
addParam(result, r.key, r.value)
}
return true
})
}
return n.forEach(func(k string, v *node) bool {
if r := match(k, route); r.found && v.item != nil {
result.Item = v.item
if r.named {
addParam(result, r.key, r.value)
}
return true
}
return false
})
}
以上就是路由管理的大部分代码,整个文件也就 200 多行,逻辑也并不复杂,通读之后还是很有收获的。
大家如果感兴趣的话,可以找到项目更详细地阅读。也可以关注我,接下来还会分析其他模块的源码。
以上就是本文的全部内容,如果觉得还不错的话欢迎点赞,转发和关注,感谢支持。
推荐阅读: