Skip to content

refract(net/ghttp): refactor the route tree#4712

Open
LanceAdd wants to merge 5 commits into
gogf:masterfrom
LanceAdd:fix/ghttp
Open

refract(net/ghttp): refactor the route tree#4712
LanceAdd wants to merge 5 commits into
gogf:masterfrom
LanceAdd:fix/ghttp

Conversation

@LanceAdd

Copy link
Copy Markdown
Member

背景

Server.serveTree 是 ghttp 路由系统的核心数据结构,承载从域名到路由处理器的整棵前缀树。每次 HTTP 请求在缓存未命中时,都必须通过 searchHandlers 遍历该树来匹配路由,是真正的热路径。

原始实现将整棵树递归地表示为 map[string]any,通过硬编码字符串键区分节点语义:

  • "*fuzz" → 模糊子节点(:param / {param} / *wildcard
  • "*list" → 当前节点的处理器列表(*glist.List

这导致 searchHandlers 每处理一个 URI 段最多产生 5 次运行时类型断言,以 /api/v1/user/123(4 段)为例,单次调用约产生 16 次断言。


变更内容

新增 routeNode 结构体

用具体结构体替换递归的 map[string]any,将三种节点语义直接表达为结构体字段:

type routeNode struct {
    children map[string]*routeNode       // 精确匹配子节点(原普通字符串键)
    fuzz     *routeNode                  // 模糊子节点(原 "*fuzz" 键)
    list     *glist.TList[*HandlerItem]  // 处理器列表(原 "*list" 键)
}

Server.serveTree 字段类型由 map[string]any 改为 map[string]*routeNode

新增 4 个封装方法

方法 用途 路径
ensureList(dst) 懒初始化 list,追加到 dst 并返回 写路径
ensureFuzz() 懒初始化 fuzz 子节点并返回 写路径
ensureChild(part) 懒初始化精确匹配子节点并返回 写路径
appendList(dst) list 非 nil 时追加到 dst 读路径(热路径)

性能收益

指标 改前 改后
searchHandlers 每段断言次数 ~5 次 0 次
list 元素迭代断言 每元素 1 次 0 次
fuzz / list 字段访问 类型断言 + map 查找 直接指针解引用
doSetHandler 核心循环行数 15 行 8 行
缓存命中时断言(serveCache 1 次 1 次(不变)
外部接口破坏

- 引入 routeNode 结构体作为路由前缀树的节点
- 使用 children 字段存储精确匹配路径段,fuzz 字段存储通配符节点,list 字段存储处理器项
- 添加 ensureList、ensureFuzz、ensureChild 等辅助方法来管理节点操作
- 修改路由注册逻辑以适应新的前缀树结构
- 更新路由查找逻辑以遍历前缀树并正确处理模糊匹配和精确匹配
- 替换原有的 map[string]any 嵌套结构为类型安全的 routeNode 指针映射

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors ghttp’s core routing structure (Server.serveTree) from a map[string]any-based recursive tree with magic keys into a typed prefix trie (routeNode) to eliminate runtime type assertions on the hot path (searchHandlers).

Changes:

  • Introduced routeNode (children/fuzz/list) and changed serveTree to map[string]*routeNode keyed by domain.
  • Added small helper methods on routeNode (ensureList/ensureFuzz/ensureChild/appendList) to simplify and speed up route registration and lookup.
  • Updated route registration (doSetHandler) and lookup (searchHandlers) to use typed navigation instead of map[string]any + type assertions.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
net/ghttp/ghttp_server_router_serve.go Switch route lookup to typed trie traversal and typed handler list iteration.
net/ghttp/ghttp_server_router.go Add routeNode helper methods and refactor registration to build the typed trie.
net/ghttp/ghttp_server.go Initialize serveTree as map[string]*routeNode.
net/ghttp/ghttp.go Update Server’s serveTree type and define the routeNode struct.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread net/ghttp/ghttp_server_router.go
@gqcn gqcn added awesome It's awesome! We keep watching. #👍 labels Jul 8, 2026
@gqcn

gqcn commented Jul 8, 2026

Copy link
Copy Markdown
Member

@LanceAdd 这个改动很有意思,属于性能改进,但由于影响面较大,预计在v3版本再考虑合并。先保留该PR处于审核状态。

@gqcn gqcn changed the title fix(net/ghttp): refactor the route tree refract(net/ghttp): refactor the route tree Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

#👍 awesome It's awesome! We keep watching.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants