Golang Go语言中上班无聊简易实现trie tree并基于它实现HTTP路由

发布于 1周前 作者 caililin 来自 Go语言

Trie 树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

type Trie
func New() *Trie
func (trie *Trie) GetNode(v string) (ok bool, node *Node)
func (trie *Trie) Has(pattern string) bool
func (trie *Trie) Match(v string) (bool, *Result)
func (trie *Trie) Put(pattern string, value interface{}) error
func (trie *Trie) SetDelimeter(delimeter string)

基于该 Trie 数实现的 HTTP router

type Context
func NewContent(rw http.ResponseWriter, r *http.Request) *Context
func (context *Context) ParamInt(key string, d ...int) (int, error)
func (context *Context) ParamString(key string, d ...string) string
func (context *Context) WriteString(v string)
type Handler
func NewHanlder() *Handler
func (handler *Handler) Delete(handleFunc func(*Context))
func (handler *Handler) DoDelete(context *Context)
func (handler *Handler) DoGet(context *Context)
func (handler *Handler) DoPatch(context *Context)
func (handler *Handler) DoPost(context *Context)
func (handler *Handler) DoPut(context *Context)
func (handler *Handler) Get(handleFunc func(*Context))
func (handler *Handler) Patch(handleFunc func(*Context))
func (handler *Handler) Post(handleFunc func(*Context))
func (handler *Handler) Put(handleFunc func(*Context))
type HandlerInterface
type Router
func New() *Router
func (router *Router) After(pattern string, midwares ...func(context *Context))
func (router *Router) Before(pattern string, midwares ...func(*Context))
func (router *Router) Delete(pattern string, handlefunc func(*Context))
func (router *Router) Get(pattern string, handlefunc func(*Context))
func (router *Router) Patch(pattern string, handlefunc func(*Context))
func (router *Router) Post(pattern string, handlefunc func(*Context))
func (router *Router) Put(pattern string, handlefunc func(*Context))
func (router *Router) Router(pattern string, handler HandlerInterface)
func (router *Router) ServeHTTP(rw http.ResponseWriter, r *http.Request)

示例

package main

import ( “fmt” “net/http” “os”

"github.com/importcjj/trie.go/router"

)

func Helloworld(ctx *router.Context) { ctx.WriteString(“hello, world!”) }

func ParamHandler(ctx *router.Context) { username := ctx.ParamString(“username”) text := fmt.Sprintf(“hi, %s”, username) ctx.WriteString(text) }

var PageResource = &router.Handler{ OnGet: func(ctx *router.Context) { filepath := ctx.ParamString(“filepath”) text := fmt.Sprintf(“Get page %s”, filepath) ctx.WriteString(text) },

OnPost: func(ctx *router.Context) {
    filepath := ctx.ParamString("filepath")
    text := fmt.Sprintf("Post page %s", filepath)
    ctx.WriteString(text)
},

}

// BasicAuth is a Midwares func BasicAuth(ctx *router.Context) { fmt.Fprintln(os.Stderr, ctx.Request.URL, “Call Basic Auth.”) }

// BeforeMetric mark a time point when the request start. func BeforeMetric(ctx *router.Context) { // just a example, so use the params map to // record the time. ctx.Params[“time”] = time.Now().Format(“Mon Jan 2 15:04:05 -0700 MST 2006”) }

// AfterMetric log the time spent to handle the requeset. func AfterMetric(ctx *router.Context) { start, _ := time.Parse(“Mon Jan 2 15:04:05 -0700 MST 2006”, ctx.Params[“time”]) dur := time.Since(start) fmt.Fprintf(os.Stderr, “%s spent”, dur.String()) }

var r = router.New()

func init() { r.Get("/hello/world", Helloworld) r.Get("/hi/<username:str>", ParamHandler) // restful api style, this pattern can match such as // “/page/hi.html” “/page/static/inde.html” eta. r.Router("/page/<filepath:*>", PageResource)

r.Before("/", BasicAuth, BeforeMetric)
r.After("/", AfterMetric)

}

func main() { server := &http.Server{ Addr: “:8080”, Handler: r, } server.ListenAndServe() }

项目地址: https://github.com/importcjj/trie.go

没有花很多时间,没有进行彻底测试。不过简单测试了一下,没有发现什么问题,性能也还过的去。如果可以的话,希望大家去试试,提一点意见。如果觉得写得可以的话,欢迎 star 和 fork 哦!然后,基于该 HTTP router 可以实现一个简单的 web 框架(懒得搞了)。有兴趣的同学可以试试。


Golang Go语言中上班无聊简易实现trie tree并基于它实现HTTP路由

更多关于Golang Go语言中上班无聊简易实现trie tree并基于它实现HTTP路由的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

上班时写得东西适合开源吗?

我这个库虽然是为公司使用写的,但是却是 100%的下班时间+个人设备的产物。

https://github.com/jamesruan/sodium

更多关于Golang Go语言中上班无聊简易实现trie tree并基于它实现HTTP路由的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


不是为公司写的,主要是没事干。

公司不管你做别的事情么

在Go语言中实现一个简单的Trie树,并基于它来实现HTTP路由,是一个既有趣又实用的练习。Trie树(前缀树)非常适合处理字符串集合的查询问题,特别是像HTTP路由这种需要快速匹配URL路径的场景。

实现Trie树

  1. 定义Trie节点:每个节点包含一个字符和指向其子节点的映射(map)。
  2. 插入操作:从根节点开始,按字符依次遍历或创建子节点,直到插入完整路径。
  3. 查找操作:同样从根节点开始,按字符查找路径,如果中途某个字符不存在则匹配失败。

基于Trie树的HTTP路由

  1. 初始化Trie树:在HTTP服务器启动时,将所有路由路径插入Trie树中。
  2. 处理请求:当HTTP请求到来时,提取URL路径,然后在Trie树中查找。
  3. 匹配成功:如果找到完整的路径,则调用相应的处理函数。
  4. 匹配失败:如果中途某个字符不匹配,则可以选择返回404错误,或者寻找最接近的匹配(可选)。

这种方法的优点是查找效率高,特别是在有大量路由的情况下,Trie树可以显著减少匹配时间。不过,需要注意的是,对于参数化路由(如/users/:id),Trie树需要一些额外的逻辑来处理参数匹配和提取。

希望这个简要的回答能帮助你理解如何在Go语言中实现Trie树并应用于HTTP路由。如果有更具体的问题或需要代码示例,请随时提问!

回到顶部