递归插入和搜索实现服务框架

举报
码乐 发表于 2025/03/05 13:44:36 2025/03/05
50 0 0
【摘要】 1 简介本文代码模板是一个最小型 Web 框架,包含: Radix 树路由匹配 Context 封装请求响应 中间件机制 JSON 响应运行方式:保存代码到 webwork.go执行 go run webwork.go访问 http://localhost:8080/ping 2 代码和解释这个示例中实现了类似 Radix 树 (基数树) 的路由管理,但还不算完全的...

1 简介

本文代码模板是一个最小型 Web 框架,包含:

    Radix 树路由匹配
    Context 封装请求响应
    中间件机制
    JSON 响应

运行方式:

保存代码到 webwork.go
执行 go run webwork.go

访问 http://localhost:8080/ping

2 代码和解释

这个示例中实现了类似 Radix 树 (基数树) 的路由管理,但还不算完全的 Radix 树实现,原因在于:

✅ 体现 Radix 树特性的部分:

公共前缀匹配:代码中通过 strings.HasPrefix() 判断路径的公共前缀。
子节点管理:每个节点存储 children map[string]*RadixNode,表示多叉节点。
递归插入和搜索:路径被分段进行匹配,符合 Radix 树逐层深入匹配的思路。

❌ 不完整的地方:

路径压缩:真实的 Radix 树应该将公共前缀直接合并到节点路径中,而不是像这里直接存完整路径。
动态路由参数:没有实现 /user/:id 这种通配符匹配。
回溯优化:没有实现路径回退或者模糊匹配。

如果希望将这个代码完善为完整的 Radix 树路由匹配器,可以按照以下步骤改造:

  节点路径保存公共前缀 (prefix)
  动态路由参数匹配 (:id 或 *wildcard)
  路径压缩(合并公共前缀)
  支持模糊匹配和可选路径
  自定义中间件处理链
  • 完整代码

    // Context 封装请求和响应
    type Context struct {
        Writer  http.ResponseWriter
        Request *http.Request
        Params  map[string]string
        index   int
        handlers []HandlerFunc
    }
    
    type HandlerFunc func(*Context)
    
    func (c *Context) JSON(status int, data string) {
        c.Writer.Header().Set("Content-Type", "application/json")
        c.Writer.WriteHeader(status)
        c.Writer.Write([]byte(data))
    }
    
    func (c *Context) Next() {
        c.index++
        for c.index < len(c.handlers) {
            c.handlers[c.index](c)
            c.index++
        }
    }
    
    // 路由节点
    type RadixNode struct {
        path     string
        handler  HandlerFunc
        children map[string]*RadixNode
    }
    
    func NewRadixNode() *RadixNode {
        return &RadixNode{children: make(map[string]*RadixNode)}
    }
    
    func (n *RadixNode) Insert(path string, handler HandlerFunc) {
        if path == "" {
            n.handler = handler
            return
        }
        for prefix, child := range n.children {
            if strings.HasPrefix(path, prefix) {
                child.Insert(path[len(prefix):], handler)
                return
            }
        }
        n.children[path] = &RadixNode{path: path, handler: handler, children: make(map[string]*RadixNode)}
    }
    
    func (n *RadixNode) Search(path string) HandlerFunc {
        if path == "" && n.handler != nil {
            return n.handler
        }
        for prefix, child := range n.children {
            if strings.HasPrefix(path, prefix) {
                return child.Search(path[len(prefix):])
            }
        }
        return nil
    }
    
    // Web框架引擎
    type Engine struct {
        route *RadixNode
    }
    
    func NewEngine() *Engine {
        return &Engine{route: NewRadixNode()}
    }
    
    func (e *Engine) GET(path string, handler HandlerFunc) {
        e.route.Insert(path, handler)
    }
    
    func (e *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
        handler := e.route.Search(req.URL.Path)
        if handler != nil {
            c := &Context{Writer: w, Request: req, handlers: []HandlerFunc{handler}}
            c.Next()
        } else {
            http.NotFound(w, req)
        }
    }
    
    func main() {
        r := NewEngine()
    
        r.GET("/ping", func(c *Context) {
            c.JSON(200, `{"message": "pong"}`)
        })
    
        http.ListenAndServe(":8080", r)
        fmt.Println("Server is running at :8080")
    }
    
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。