百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

httprouter路由框架为什么高性能?

ccwgpt 2025-07-08 16:58 2 浏览 0 评论

httprouter是非常高效的http路由框架,gin框架的路由也是基于此库

地址:
https://github.com/julienschmidt/httprouter

一、使用方法

使用方法也比较简单,如下:

package main

import (
    "fmt"
    "net/http"
    "log"

    "github.com/julienschmidt/httprouter"
)

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    fmt.Fprint(w, "Welcome!\n")
}

func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
    fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
}

func main() {
    router := httprouter.New()
    router.GET("/", Index)
    router.GET("/hello/:name", Hello)

    log.Fatal(http.ListenAndServe(":8080", router))
}

二、前缀树

这里在前文已经描述过了,详情看beego框架的路由

三、具体实现

1、Router

type Router struct {
	  trees map[string]*node // 存储了http不同方法的根节点
  
	  paramsPool sync.Pool
	  maxParams  uint16
	  SaveMatchedRoutePath bool
	  // 是否通过重定向,给路径自添加/
	  RedirectTrailingSlash bool
	  // 是否通过重定向,自动修复路径,比如双斜杠等自动修复为单斜杠
	  RedirectFixedPath bool
	  // 是否检测当前请求的方法被允许
	  HandleMethodNotAllowed bool
	  // 是否自定答复OPTION请求
	  HandleOPTIONS bool
	  GlobalOPTIONS http.Handler
	  globalAllowed string
	  // 404处理
	  NotFound http.Handler
	  // 不被允许的方法处理
	  MethodNotAllowed http.Handler
	  // 异常处理
	  PanicHandler func(http.ResponseWriter, *http.Request, interface{})
}

这里的trees同样是存储了方法树,每一个不同的方法都有一个前缀树。

这里的httproute性能比beego高的一个原因是它使用的sync.Pool来优化内存的使用。

2、路由注册

在调用Handle方法的时候插入路由到路由树中。

func (r *Router) Handle(method, path string, handle Handle) {
	  varsCount := uint16(0)
  
	  if method == "" {
	  	  panic("method must not be empty")
	  }
	  if len(path) < 1 || path[0] != '/' {
	  	  panic("path must begin with '/' in path '" + path + "'")
	  }
	  if handle == nil {
	  	  panic("handle must not be nil")
	  }
  
	  if r.trees == nil {
	  	  r.trees = make(map[string]*node)
	  }
  
	  root := r.trees[method]
	  if root == nil {
	  	  root = new(node)
	  	  r.trees[method] = root
  
	  	  r.globalAllowed = r.allowed("*", "")
	  }
  
      // 添加路由到前缀树中
	  root.addRoute(path, handle)
  
	  // Lazy-init paramsPool alloc func
	  // 初始化pool
	  if r.paramsPool.New == nil && r.maxParams > 0 {
	  	  r.paramsPool.New = func() interface{} {
	  		    ps := make(Params, 0, r.maxParams)
	  		    return &ps
	  	}
	  }
}

3、插入算法

这里插入路由树的方式和beego不同,beego是按照路由/来分割的,比如/user和/userinfo这是对应的两个子树,而httprouter将相同前缀合并,/user是父节点。

下面给个例子

Priority   Path             Handle
9            \                      *<1>
3            ├s                    nil
2            |├earch\          *<2>
1            |└upport\        *<3>
2            ├blog\             *<4>
1            |    └:post         nil
1            |         └\          *<5>
2            ├about-us\      *<6>
1            |        └team\   *<7>
1            └contact\        *<8>

同样,节点被区分了几种类型

type nodeType uint8

const (
	  static nodeType = iota // default 普通节点
	  root			// 根节点
	  param			// 参数节点
	  catchAll		// 通配符
)

而节点的数据结构为

type node struct {
	  path      string		// 节点对应的路径
	  indices   string
	  wildChild bool			// 是否是通配符
	  nType     nodeType		// 节点类型
	  priority  uint32
	  children  []*node		// 子节点
	  handle    Handle
}

4、查找路由

httprouter是实现了net/http的ServeHTTP方法

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	  if r.PanicHandler != nil {
	  	  defer r.recv(w, req)
	  }
  
	  path := req.URL.Path
  
	  if root := r.trees[req.Method]; root != nil {
	  	  if handle, ps, tsr := root.getValue(path, r.getParams); handle != nil {
	  	  	  if ps != nil {
	  	  	  	  handle(w, req, *ps)
	  	  	  	  r.putParams(ps)
	  	  	  } else {
	  	  	  	   handle(w, req, nil)
	  	  	  }
	  	  	  return
	  	  } 
            // 重定向逻辑
	  }
	  // 异常处理逻辑
}

这里接受到http请求,根据请求的方法和路由信息,查找路由树。

然后根据路由和路由树进行对比,获取到执行的方法。

这一部分比beego的处理稍显简洁。

四、总结

httprouter使用的路由树比beego的路由树更加高效

1、对前缀树再优化,减少了重复的前缀。

2、对路由上的参数获取使用sync.Pool方式接受,减少了内存的分配。

相关推荐

Android开发基础入门(一):UI与基础控件

Android基础入门前言:从今天开始,我们开始分享Android客户端开发的基础知识。一、工具指南工欲善其事必先利其器,我们首先介绍一下开发Android常用的集成开发环境。小雨在上大学期间,开发a...

谷歌Material Design质感设计UI开发框架

谷歌MaterialDesign质感设计是一个新的用户界面设计概念,即将到来的Android版本称为“AndroidL”中会使用这种设计语言。在这篇文章中,我们收集出最新的和最好的Android...

Android主流UI开源库整理(android 开源ui)

前言最近老大让我整理一份Android主流UI开源库的资料,以补充公司的Android知识库。由于对格式不做特别限制,于是打算用博客的形式记录下来,方便查看、防丢并且可以持续维护、不断更新。标题隐...

系统工具类App的开发框架(系统开发方法工具)

系统工具类App的开发框架选择,很大程度上取决于目标平台(Android、iOS或两者兼有),以及对性能、系统级访问深度和开发效率的需求。由于这类App常常需要深入操作系统底层,因此原生开发框架通常是...

2025年vue前端框架前瞻(vue前端开发规范手册)

Vue是一个轻量且灵活的JavaScript框架,广受开发者喜爱,因其简单易用的API和组件化的开发方式而闻名。Vite是一个现代化的前端构建工具,以其极快的开发服务器启动速度和热模块替换...

前端流行框架Vue3教程:28. Vue应用

28.Vue应用应用实例每个Vue应用都是通过createApp函数创建一个新的应用实例main.jsimport{createApp}from'vue'import...

2024 Vue 最全的生态工具组合推荐指南

Vue3虽然Vue2很多项目在用,但是官方已经宣布不再维护Vue2,所以新项目肯定首选Vue3来进行开发,组合式API开发起来比选项式API方便多了,而且Vue3的响应式实现也更...

基于 Vue3 Element Plus 的中后台管理系统模板

PureAdmin是一个开源的前端中后台管理系统模板,基于Vue3、Element-Plus,支持移动端、国际化、多主题设置,支持前端静态路由、后端动态路由配置,旨在为开发人员提供一个易于使用、高...

重磅!滴滴开源全新跨端小程序框架,基于 Vue 3!

最近,滴滴出行开源了自主研发的全新轻量级跨端小程序框架——星河(Dimina),为开发者提供了“一次开发,多端运行”的高性能、低门槛解决方案。下面就来一览Dimina的魅力!什么是星河(Dim...

【推荐】一款基于 Vue + .NET 8 开源、免费、功能强大的快速开发框架

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!项目介绍Vue.NetCore是一款集高效、灵活、易于扩展于一体的快速开发框架(基于Vue提供Vue2/Vue...

搭建Trae+Vue3的AI开发环境(vue ide 开发工具)

从2024年2025年,不断的有各种AI工具会在自媒体中火起来,号称各种效率王炸,而在AI是否会替代打工人的话题中,程序员又首当其冲。作为一个后端开发,这篇文章基于Trae工具,来创建和运行一个简单的...

一款基于 Vue + .NET 8 开源、免费、功能强大的快速开发框架

项目介绍Vue.NetCore是一款集高效、灵活、易于扩展于一体的快速开发框架(基于Vue提供Vue2/Vue3版本和.NET8前后端分离),适用于多种应用场景。通过前后端分离的设计、强大的...

盘点一下这些年PHP在桌面应用方面的解决方案

今天作者给大家盘点一下近些年PHP在实现桌面客户端方面的项目。PHP-GTKPHP-GTK是2001年3月创立,是PHP的一个扩展,实现了与GTK+的绑定,提供面向对象的接口,极大地简化了客户端跨平台...

PHP+Uniapp校园圈子系统校园论坛小程序开发:踩坑与优化经验分享

一、系统架构与技术选型1.架构设计采用前后端分离架构,前端使用Uniapp实现跨端开发(支持微信小程序、H5、App),后端基于PHP(推荐ThinkPHP或Laravel框架)提供RESTful...

智能匹配+安全护航:PHP代练系统护航小程序如何提升用户信任?

在代练行业中,用户信任是平台发展的核心要素。基于PHP后端与uni-app跨端框架的代练系统,通过智能匹配与安全护航两大核心策略,能够有效提升用户信任,构建健康可持续的代练生态。以下从技术实现与用户体...

取消回复欢迎 发表评论: