gin框架源码分析——路由模块

2023-11-17

一、什么是gin框架

gin的官方简介如下:

gin is a web framework written in Go (Golang). It features a martini-like API with performance that is up to 40 times faster thanks to httprouter. If you need performance and good productivity, you will love gin.
gin是一个用Go (Golang)编写的web框架。类似于一个Martini的API,由于使用了httprouter,性能提高了40倍。如果您需要良好的表现和工作效率,您会喜欢gin。

gin框架速度很快, 这也是在企业中被广泛使用的原因之一。gin之所以能够提供高效的路由解析,是因为使用了前缀树这样的数据结构来进行path和handler方法的映射,本篇文章就来探讨gin框架的路由模块。

二、gin初始化的过程

1、Engine的实例化
Engine是容器对象,是整个框架的基础。gin提供了两个方法来创建Engine实例,New和Default方法。

// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
	debugPrintWARNINGDefault()
	//Default()方法也调用了New()方法来创建Engine实例
	engine := New()
	engine.Use(Logger(), Recovery())
	return engine
}

default方法除了包含New方法外,还增加了两个中间件,Logger是默认系统输出日志,Recovery是在报panic的时候恢复系统输出并返回500。
New()方法:

// New returns a new blank Engine instance without any middleware attached.
// By default the configuration is:
// - RedirectTrailingSlash:  true
// - RedirectFixedPath:      false
// - HandleMethodNotAllowed: false
// - ForwardedByClientIP:    true
// - UseRawPath:             false
// - UnescapePathValues:     true
func New() *Engine {
	debugPrintWARNINGNew()
	engine := &Engine{
	//RouterGroup是管理路由和中间件的组件,它定义了URL路径与处理函数的映射关系。
		RouterGroup: RouterGroup{
			Handlers: nil,
			basePath: "/",
			root:     true,
		},
		FuncMap:                template.FuncMap{},
		//RedirectTrailingSlash当前路径处理函数不存在时,是否允许重定向到路径+或-"/"的处理函数
		RedirectTrailingSlash:  true,
		//RedirectFixedPath路由未命中时,是否允许修复当前处理路径(如对路径大小写不敏感查询、删除多余路径元素等)并重定向
		RedirectFixedPath:      false,
		//HandleMethodNotAllowed路由未命中时...这个我也暂时不明白啥意思
		HandleMethodNotAllowed: false,
		//ForwardedByClientIP是否转发客户端ip
		ForwardedByClientIP:    true,
		//AppEngine如果启用该引擎,将插入一些以”X-AppEngine..."开头的标题,以便更好地与PaaS集成
		AppEngine:              defaultAppEngine,
		//UseRawPath是否使用未转义的请求路径,即url.RawPath,默认为false。如果为true,url.RawPath将用于查找参数。
		UseRawPath:             false,
		RemoveExtraSlash:       false,
		//UnescapePathValues
		UnescapePathValues:     true,
		MaxMultipartMemory:     defaultMultipartMemory,
		trees:                  make(methodTrees, 0, 9),
		delims:                 render.Delims{Left: "{{", Right: "}}"},
		secureJsonPrefix:       "while(1);",
	}
	engine.RouterGroup.engine = engine
	engine.pool.New = func() interface{} {
		return engine.allocateContext()
	}
	return engine
}

创建的Engine实例,与路由匹配相关的有RouterGroup、trees、engin.pool.New这三个参数.

三、Engine中与路由相关的参数

1.路由相关参数的调用

参数调用流程

2. 重要参数详解

(1).RouterGroup

RouterGroup结构体:

// RouterGroup is used internally to configure router, a RouterGroup is associated with
// a prefix and an array of handlers (middleware).
type RouterGroup struct {
	Handlers HandlersChain
	basePath string
	engine   *Engine
	root     bool
}

回调函数:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

Handler为中间件数组,Handler的类型为HandlersChain,是方法类型HandlerFunc的数组。HandlerFunc是参数为*Context的回调函数。

// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)

// HandlersChain defines a HandlerFunc array.
type HandlersChain []HandlerFunc

注:Handler、HandlerFunc、Handle、HandlerFunc的区别:

//Handler
type Handler interface{
	ServeHTTP(ResponseWriter, *Request)
}

//HandlerFunc
type HandlerFunc func(ResponseWriter, *Request)

//Handler, 一个是方法,一个是函数 (方法是包含了接收者的函数)
func (mux *ServeMux) Handler(pattern string, handler Handler)
func Handler(pattern string, handler Handler)

//HandlerFunc,与Handler同理,一个是方法,一个是函数
func (mux *ServeMux) HandlerFunc(pattern string, callback HandlerFunc)
func HandlerFunc(pattern string, callback HandlerFunc)

Handler : Handler是一个接口,实现了ServeHTTP方法,这个ServeHHTTP方法其实就是一个回调函数,用于处理http请求。
HandlerFunc: HandlerFunc是一个回调函数类型的别名,等价于Handler的ServeHTTP方法。
Handle:用于给我们的WEB程序注册路由,传入的第二个参数是一个Handler。
HandleFunc: 与Handle一样,只不过传入的第二个参数是一个HandlerFunc。
Handle和HandleFunc基本是等价的,它们都代表了如何处理一个http请求,拿到一个Handler以及HandlerFunc,只是在使用上略微不同。

(2).trees

trees是最重要的一部分,负责路由和handler方法的映射,因为它gin框架才实现了高性能的路由匹配。
结构体类似一个key-value类型的字典树,key为字符串格式的路由,value为[]HandlerFunc,这个方法数组存储的是按顺序的中间件和handler方法。
第一部分中,gin框架创建的Engine实例,tree是make(methodTrees, 0, 9),make方法创建的切片,初始长度为0,预留总长度为9.
methodTrees和methodTree结构:

type methodTree struct {
	method string
	root   *node
}

type methodTrees []methodTree

methodTrees是[]methodTree,而methodTree是由string类型的method和node类型的指针组成。
method是HTTP的访问方法,Go中一共分为9中,也就是说methodTree数组最多有9棵树。
Go支持的的HTTP访问方法:

package http

// Common HTTP methods.
//
// Unless otherwise noted, these are defined in RFC 7231 section 4.3.
const (
	MethodGet     = "GET"
	MethodHead    = "HEAD"
	MethodPost    = "POST"
	MethodPut     = "PUT"
	MethodPatch   = "PATCH" // RFC 5789
	MethodDelete  = "DELETE"
	MethodConnect = "CONNECT"
	MethodOptions = "OPTIONS"
	MethodTrace   = "TRACE"
)

每一种方法对应一个node根节点
node的结构和类型:

type nodeType uint8

const (
	static nodeType = iota // default
	root
	param
	catchAll
)

type node struct {
    //path是当前节点的相对路径
	path      string
	//indices是目录,由所有子节点的path[0]组成的字符串
	indices   string
	//children是所有的子节点
	children  []*node
	//handlers是包括中间件的一系列当前节点的处理函数
	handlers  HandlersChain
	//priority是当前节点及子孙节点的实际路由数量,即经过该节点有多少条路径,等同于前缀树中节点的path值(一个节点的子孙节点越多,权重越大,该节点在其父节点的indices目录中越靠前,在父节点的children数组中也越靠前)
	priority  uint32
	//nType是当前节点的类型:
//nodeType分为四种类型,默认为static是普通类型节点,root是根节点,即methodTree结构体中与method一一对应的节点,param是参数路由类型的节点,即路由中可以夹带参数,例如/path/:id,:后到下一个/之前的内容会赋值给id,catchAll是匹配所有内容的路由,如/path/*id,*号后面所有的内容都会赋值给参数id,包括所有/。
	nType     nodeType
	//maxParams是子孙节点的最大参数数量
	maxParams uint8
	//wildChild是一个bool值,表示孩子节点是否有通配符
	wildChild bool
	//fullPath是所有子孙节点路径的最长前缀
	fullPath  string
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gin框架源码分析——路由模块 的相关文章

  • 海量数据存储之Key-Value存储简介

    转自 http forchenyun iteye com blog 744935 Key value存储简介 具备高可靠性及可扩 展性的海量数据存储对互联网公司来说是一个巨大的挑战 传统的数据库往往很难满足该需求 并且很多时候对于特定的系统
  • V2X应用场景之协同式自动驾驶

    转自 http zhidx com p 96637 html V2X应用场景之协同式自动驾驶 这个应用场景我觉得是比较典型的 也想多花点时间给大家介绍一下 就是关于V2X在自动驾驶里面很典型的应用 我们管它叫协同式自动驾驶车队 什么意思呢

随机推荐

  • DockerFile详细介绍

    dockerfile 文件中的常见指令 详细教程地址 ADD 复制和解包文件 COPY 复制文本 CMD 指定这个容器启动的时候要运行的命令 只有最后一个会生效可被替代 ONBUILD 当构建一个被继承DockerFile 这个时候就会运行
  • Mysql多对多查询

    1 多对多需要三张表 如图所示 2 对应是SQL语句 SELECT A aname B hobby FROM A B AB WHERE A id AB aid AND B id AB bid 3 对应的查询结果
  • A list of Go projects

    Indexes and search engines These sites provide indexes and search engines for Go packages godoc org go search gowalker S
  • Python 实现FIR低通滤波器设计

    FIR Finite Impulse Response 有限脉冲响应 低通滤波器是一种数字滤波器 它可以在数字信号处理中用来对信号进行低通滤波 下面是一个简单的 Python 代码示例 用于设计 FIR 低通滤波器 import numpy
  • Oracle查看主键、删除主键以及新增联合主键

    Oracle查看主键 删除主键以及新增联合主键 主键是用于唯一标识表中的每一条数据的 不能重复也不能为null 一个表中不能有多个独立的主键 但是一个表中可以有联合主键 即多个字段组合 一 查看主键 SELECT FROM USER CON
  • vue中常用的7个属性

    1 el属性 用来指示vue编译器从什么地方开始解析 vue的语法 可以说是一个占位符 2 data属性 用来组织从view中抽象出来的属性 可以说将视图的数据抽象出来存放在data中 3 template属性 用来设置模板 会替换页面元素
  • 字节序转换

    一 概念 1 小端法 Little Endian 就是低位字节排放在内存的低地址端 即该值的起始地址 高位字节排放在内存的高地址端 2 大端法 Big Endian 就是高位字节排放在内存的低地址端 即该值的起始地址 低位字节排放在内存的高
  • Java Swing基础(顶层容器,中间层容器,原子组件)

    Swing基础 Swing顶层容器 Swing的3个顶层容器类 JFrame JApplet JDialog 都是重量级组件 分别继承了AWT组件Frame Applet和Dialog 每个顶层容器都有一个内容面板 通常直接或间接的容纳别的
  • 目前支持CUDA的nVIDIA的显卡型号 驱动及其 修改过后的 inf文件

    下载169 21 forceware winxp 32bit english whql exe NVIDIA Driver for Microsoft Windows XP with CUDA Support 169 21 我们在运行它的时
  • JDK8 网络Net包研究(二)

    完整的Socket 客户端 和 服务端实例代码 Client package lang socket import java io BufferedReader import java io IOException import java
  • 软件测试 git和gitee集成Pycharm 基于Flask的Mock Server服务器

    文章目录 1 Git 1 1 作用 1 2 工具 1 3 名称解释 2 安装git和注册Gitee 3 使用Git 1 clone克隆命令 2 初始化 3 查看文件状态 4 文件提交暂存区 5 提交到本地版本库 6 修改文件 7 查看日志
  • Google Cloud裁员 !为什么这么突然?

    点击上方 KotlinPython 关注 干货立马到手 大家好 我是gao 网易科技讯 2月15日消息 据国外媒体报道 作为内部机构重组举措的一部分 谷歌旗下云计算业务部门正在削减未指定数量的工作岗位 此举旨在提高该公司在云计算这个蓬勃发展
  • 基于实例的学习方法

    基于实例的学习方法 动机 基本概念 基于实例的学习 基于实例的概念表示 1 最近邻 最近邻的例子 理论结果 最近邻 1 NN 解释 问题 K 近邻 KNN KNN讨论1 距离度量 KNN 讨论2 属性 KNN 属性归一化 KNN 属性加权
  • Python 操作excel:新建文件并写入

    这里我们用到的库是 xlwt 代码实现 import xlwt 创建workbook和sheet对象 workbook xlwt Workbook 注意Workbook的开头W要大写 因为是个类对象 sheet1 workbook add
  • 关于在Spring配置文件中解决MySQL重连问题

    com alibaba druid pool DruidDataSource或org apache commons dbcp BasicDataSource连接池 自动重连配置 1 testWhileIdle配置
  • 蓝牙耳机连接笔记本电脑音量直接爆棚

    通常手机端和耳机端都有属于自己的音量 而绝对音量 AbsoluteVolume 就指的是蓝牙耳机和手机连接播放音频时双方音量同步 也就是当手机端音量调到最大时 耳机端的音量也是最大 声音加倍 快乐加倍有没有 绝对音量也称媒体音量同步 因此可
  • JavaWeb —— Servlet(看这篇就够了,通俗易懂快速掌握)

    前言 Serlet是什么 Servlet是服务端的小组件是一门动态获取页面资源的技术 是Java语言编写的一个类 Servlet运行在Web服务器中 他是由服务端调用以及执行的 学号Servlet是非常有必要的 Servlet是MVC的基石
  • 2022最新版Python安装教程,适合新手,赶快收藏!

    想要使用好Python这样一门解释性的语言 当然 掌握好安装方法也是极为重要的 安装不好Python 有可能会为你做开发或者在其他时候带来许多不必要的麻烦 接下来话不多说 直接开始 这里主要以Windows系统为例 Python的安装 打开
  • Vivado综合warning:[Synth 8-151] case item 5‘b10000 is unreachable

    问题 三段式状态机无法遍历所有状态 解决 1 检查reg nstate cstate的位宽是否足够容纳状态 2 检查FSM2中状态跳转逻辑是否有漏洞 3 检查是否设计了不需要的状态 本例中 参数列表如下 而状态寄存器位宽如下 即位宽不匹配导
  • gin框架源码分析——路由模块

    目录 一 什么是gin框架 二 gin初始化的过程 三 Engine中与路由相关的参数 1 路由相关参数的调用 2 重要参数详解 1 RouterGroup 2 trees 一 什么是gin框架 gin的官方简介如下 gin is a we