当前位置: 首页 > news >正文

Gin框架源码解析

概要

目录

Gin路由详解

Gin框架路由之Radix Tree

一、路由树节点

二、请求方法树

三、路由注册以及匹配

中间件含义

Gin框架中的中间件


        主要讲述Gin框架路由和中间件的详细解释。本文章将从Radix树(基数树或者压缩前缀树)、请求处理、路由方法树、路由的注册与匹配以及中间件的详细解释这五大部分入手。

        Gin 框架 路由使用前缀树,路由注册的过程就是构造前缀树的过程,路由匹配的过程是查找前缀树 的过程。

Gin路由详解

Gin框架使用的是定制版本的httprouter。我们简单介绍下关于httprouer框架。

Httprouter是一个高性能路由分发器,它负责将不同方法的多个路径分别注册到各个handle函数。当收到请求时,Httprouter会快速查找请求的路径是否有相对应的处理函数,并执行相应的业务逻辑处理。

Httprouter使用基数树(radix tree)来进行高效的路径查找,这种数据结构适用于需要快速查找和匹配的场景。此外,Httprouter还支持两种通配符匹配,使得路由规则更加灵活和强大。

它为Gin提供了高效、灵活的路由匹配功能,使得Gin成为了一个高性能的Web框架。同时,Httprouter也是Go语言中广泛使用的一个路由库,独立于Gin框架,可以被其他Go语言的Web框架所使用。

Gin框架路由之Radix Tree

Radix Tree 是一种更节省空间的前缀树。对于基数树的每个节点,如果该节点是唯一的子树的话,就和父节点合并。

Radix Tree 可以被认为是一个简洁版的前缀树。我们注册路由的过程就是在构造前缀树的过程,具有公共前缀的节点也共享一个公共父节点。

如下图所示:GET方法对应的路由树。

  1. Priority(优先级):每个树级别上的子节点都按照优先级排序,其中优先级就是在子节点上注册的句柄数量。优点:优先匹配被大多数路由路径包含的节点(更快速定位)、最长路径可以优先匹配(成本补偿)。
  2. Handle: Get每个路由对应的实现函数。*<数字> 表示Handle处理函数的内存地址。

URL具有层级结构,并且都是有限的字符组,所以有很多常见的前缀。这样是的我们很容易将路由简化为更小的问题。

路由器为每种请求方法管理一颗单独的树

一、路由树节点

type node struct {// 节点路径,比如上面的s,earch,和upportpath      string// 和children字段对应, 保存的是分裂的分支的第一个字符// 例如search和support, 那么s节点的indices对应的"eu"// 代表有两个分支, 分支的首字母分别是e和uindices   string// 儿子节点children  []*node// 处理函数链条(切片)handlers  HandlersChain// 优先级,子节点、子子节点等注册的handler数量priority  uint32// 节点类型,包括static, root, param, catchAll// static: 静态节点(默认),比如上面的s,earch等节点// root: 树的根节点// catchAll: 有*匹配的节点// param: 参数节点nType     nodeType// 路径上最大参数个数maxParams uint8// 节点是否是参数节点,比如上面的:postwildChild bool// 完整路径fullPath  string
}

二、请求方法树

        每一个HTTP method都对应一颗radix树,我们注册路由的时候都会调用addRoute函数。函数含义我们可以看到在注册路由的时候都是先根据请求方法获取对应的树,也就是gin框架会为每一个请求方法创建一颗对应的树。只不过需要注意一个细节是gin框架中请求方法对应树关系并不是使用map而是使用的切片,engine.trees的类型是methodThrees

type methodTree struct {method stringroot   *node
}type methodTrees []methodTree  // slicefunc (engine *Engine) addRoute(method, path string, handlers HandlersChain) {// liwenzhou.com...// 获取请求方法对应的树root := engine.trees.get(method)if root == nil {// 如果没有就创建一个root = new(node)root.fullPath = "/"engine.trees = append(engine.trees, methodTree{method: method, root: root})}root.addRoute(path, handlers)
}

考点 :为什么用切片存储请求方法树,而不用map?

        节省内存。HTTP请求方法数量也就9种,用切片存储和查询效率足够。只需要做出一次性内存申请即可。

三、路由注册以及匹配

        路由注册函数:

  1. addRoute函数:将具有给定句柄的节点添加到路径中。不是并发安全的函数。
  2. insertChild函数:根据path本身进行分割,将/分开的部分分别作为节点保存,形成一颗树结构。参数匹配中的 : 和 *  的区别是,前者是匹配一个字段,后者是匹配后面所有的路径。

        路由匹配:


func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {// 这里使用了对象池c := engine.pool.Get().(*Context)// 这里有一个细节就是Get对象后做初始化c.writermem.reset(w)c.Request = reqc.reset()engine.handleHTTPRequest(c)  // 我们要找的处理HTTP请求的函数engine.pool.Put(c)  // 处理完请求后将对象放回池子
}func (engine *Engine) handleHTTPRequest(c *Context) {// 根据请求方法找到对应的路由树t := engine.treesfor i, tl := 0, len(t); i < tl; i++ {if t[i].method != httpMethod {continue}root := t[i].root// 在路由树中根据path查找value := root.getValue(rPath, c.Params, unescape)if value.handlers != nil {c.handlers = value.handlersc.Params = value.paramsc.fullPath = value.fullPathc.Next()  // 执行函数链条c.writermem.WriteHeaderNow()return}c.handlers = engine.allNoRouteserveError(c, http.StatusNotFound, default404Body)
}

        路由匹配是由节点的GetValue方法实现的。getValue根据给定的路径返回nodeValue值,里面保存的处理函数和匹配到的路径参数数据。如果找不到任何处理函数,会尝试TSR(尾随斜杠重定向)。 

中间件含义

        中间件是指处理HTTP请求的函数或组件,通常用于在请求到达目标处理程序之前或之后执行一些处理逻辑。中间件在Go语言中经常被使用,因为它提供了一种可扩展和可重用的机制,用于处理身份验证、授权、日志记录、错误处理等常见的Web应用程序需求。

        中间件在Go语言主要是因为它提供了一种灵活、可扩展和可重用的机制,用于处理Web应用程序中的各种需求和逻辑。

        中间件优势:

  1. 函数式编程思想:Go语言支持函数式编程风格,而中间件提供了一种将函数作为参数传递并在请求处理过程中进行组合和调用的机制。使得代码更加模块化和可重用性。
  2. 请求处理流程的可扩展性:中间件允许开发人员将请求处理流程分解为多个独立的函数或组件,这些 组件可以按照特定的顺序组合和调用。这种可扩展性使得开发人员可以轻松的添加、移除或替换中间件,以满足特定的应用程序需求。
  3. 前后置处理逻辑:中间件可以在请求到达目标处理程序之前或之前执行一些处理逻辑,例如身份验证、日志记录、错误处理等。这种机制使得开发人员可以轻松的请求处理过程中添加前后置处理逻辑,而无需修改现有的代码。
  4. 社区支持和普及。

Gin框架中的中间件

        gin框架中涉及中间件相关有4个常用的方法,c.Next() 、c.Abort() 、c.Set()、c.Get()

        Gin中间件函数和处理函数是以切片的形式调用链条存在的,我们可以顺序调用也可以借助c.Next函数方法实现嵌套调用。

  c.Set()c.Get()这两个方法多用于在多个函数之间通过c传递数据的,比如我们可以在认证中间件中获取当前请求的相关信息(userID等)通过c.Set()存入c,然后在后续处理业务逻辑的函数中通过c.Get()来获取当前请求的用户。c就像是一根绳子,将该次请求相关的所有的函数都串起来了。

        c.Abort()中断整个调用链条,从当前函数返回。

相关文章:

Gin框架源码解析

概要 目录 Gin路由详解 Gin框架路由之Radix Tree 一、路由树节点 二、请求方法树 三、路由注册以及匹配 中间件含义 Gin框架中的中间件 主要讲述Gin框架路由和中间件的详细解释。本文章将从Radix树&#xff08;基数树或者压缩前缀树&#xff09;、请求处理、路由方法树…...

MacOS设置JAVA_HOME环境变量

首先先查看一下&#xff0c;系统当前使用的java是谁&#xff0c;可以使用/usr/libexec/java_home命令 % /usr/libexec/java_home /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home检查一下这个路径下的文件&#xff0c;发现这是一个jre的目录。加上-V参数看…...

闭眼检测实现

引言 这段代码是一个实时眼睛状态监测程序&#xff0c;可以用于监测摄像头捕获的人脸图像中的眼睛状态&#xff0c;判断眼睛是否闭合。具体应用实现作用说明如下&#xff1a; 1. 实时监测眼睛状态 通过摄像头捕获的实时视频流&#xff0c;检测人脸关键点并计算眼睛的 EAR&a…...

系列六、Java垃圾回收器主要有哪些?

一、Java垃圾回收器主要有哪些? UseSerialGC、UseParallelGC、UseConcMarkSweepGC、UseParallelNewGC、UseParallelOldGC、UseG1GC...

【7】Spring Boot 3 集成组件:缓存组件 spring cache + spring data redis

目录 【7】Spring Boot 3 集成组件&#xff1a;缓存组件 spring cache spring data redis什么是缓存抽象声明式注解JSR-107对应SpEL上下文数据 引入依赖cache 支持的缓存类型缓存类型配置NONESIMPLEREDIS自定义配置 CAFFEINE Hazelcast...总结 个人主页: 【⭐️个人主页】 需要…...

说说Java中的不可重入锁

什么是锁&#xff1f; 简单来讲在Java中&#xff0c;锁是一种用于并发控制的机制&#xff0c;用于保护共享资源&#xff0c;防止多个线程同时访问或修改数据导致的数据不一致性和线程安全问题。在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;每个对象都有一个相关联的…...

C++学习 --vector

目录 1&#xff0c; 什么是vector 2&#xff0c; 创建vector 2-1&#xff0c; 标准数据类型 2-2&#xff0c; 自定义数据类型 2-3&#xff0c; 其他创建方式 3&#xff0c; 操作vector 3-1&#xff0c; 赋值 3-2&#xff0c; 添加元素 3-2-1&#xff0c; 添加元素(assi…...

Android图片涂鸦,Kotlin(1)

Android图片涂鸦&#xff0c;Kotlin&#xff08;1&#xff09; import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Path import android.graphics.PointF import android.…...

upload-labs(1-17关攻略详解)

upload-labs pass-1 上传一个php文件&#xff0c;发现不行 但是这回显是个前端显示&#xff0c;直接禁用js然后上传 f12禁用 再次上传&#xff0c;成功 右键打开该图像 即为位置&#xff0c;使用蚁剑连接 连接成功 pass-2 源码 $is_upload false; $msg null; if (isse…...

《 机器人基础 》期末试卷(A)

一、填空题&#xff08;30分&#xff0c;每空2分&#xff09; 1. 按照相机的工作方式&#xff0c;机器人常用相机分为1&#xff09;__ 单目摄像头 2&#xff09;__ 双目摄像头 _ 3&#xff09;_深度摄像头_ 三类。 2. 度量地图强调…...

Azure Machine Learning - Azure AI 搜索中的矢量搜索

矢量搜索是一种信息检索方法&#xff0c;它使用内容的数字表示形式来执行搜索方案。 由于内容是数字而不是纯文本&#xff0c;因此搜索引擎会匹配与查询最相似的矢量&#xff0c;而不需要匹配确切的字词。本文简要介绍了 Azure AI 搜索中的矢量支持。 其中还解释了与其他 Azure…...

3 redis实现一个消息中间件

使用list实现一个队列&#xff0c;可以从左侧入队&#xff0c;也可以从右侧入对 即可以从左侧读取&#xff0c;也可以从右侧读取 1、Lindex Lindex 命令用于通过索引获取列表中的元素 也可以使用负数下标&#xff0c;以 -1 表示列表的最后一个元素&#xff0c; -2 表示列表的…...

js添加dom到指定div之后,并给添加的dom类名,然后设置其样式,以及el-popover层级z-index过高问题解决。

遇到一个需求,Vue项目做一个表格,要求表头与表格内容分开,如下效果所示,表头与表格有个高度间隔边距(箭头所示),因为默认我们的el-table的表头与内容是一起的: 思路:通过querySelector获取el-table__header-wrapper元素,通过createElement创建一个div,通过 newElem…...

C语言结构体

#include <stdio.h> #include <string.h> #include <stdlib.h>//struct Student_s { // int num; // char name[20]; // char gender; // int age; // float Chinese; // float Math; // float English; // char addr[30]; //}; //最后的分号一定要写&#x…...

【Python大数据笔记_day10_Hive调优及Hadoop进阶】

hive调优 hive官方配置url: Configuration Properties - Apache Hive - Apache Software Foundation hive命令和参数配置 hive参数配置的意义: 开发Hive应用/调优时&#xff0c;不可避免地需要设定Hive的参数。设定Hive的参数可以调优HQL代码的执行效率&#xff0c;或帮助定位问…...

React经典初级错误

文章 前言错误场景问题分析解决方案后言 前言 ✨✨ 他们是天生勇敢的开发者&#xff0c;我们创造bug&#xff0c;传播bug&#xff0c;毫不留情地消灭bug&#xff0c;在这个过程中我们创造了很多bug以供娱乐。 前端bug这里是博主总结的一些前端的bug以及解决方案&#xff0c;感兴…...

C# System.Array.CopyTo() 和 System.Array.Clone() 有什么区别

System.Array.CopyTo() 和 System.Array.Clone() 是用于数组复制的两种不同方法&#xff0c;它们在实现和用途上有一些区别。 System.Array.CopyTo() 方法&#xff1a; CopyTo() 方法用于将数组的元素复制到另一个数组。它是 Array 类的实例方法&#xff0c;可以用于复制一个…...

Stable Diffusion 启动时 got an unexpected keyword argument ‘socket_options‘ 错误解决

Stable Diffusion 启动时 got an unexpected keyword argument socket_options 错误解决 问题解决方法 问题 Launching Web UI with arguments: Traceback (most recent call last):File "launch.py", line 48, in <module>main()File "launch.py"…...

CSS 文本属性篇

文字颜色 属性名&#xff1a;color作用&#xff1a;控制文字的颜色可选值&#xff1a; 1.颜色名 color: blue; 2.rgb或rgba color:rgb(132, 220, 254); color:rgba(132, 220, 254,0.5); 3.hex或hexa&#xff08;十六进制&#xff09; color:#0078d4; color:#0078d48b; 4.hsl或h…...

Activiti,Apache camel,Netflex conductor对比,业务选型

Activiti,Apache camel,Netflex conductor对比&#xff0c;业务选型 1.activiti是审批流&#xff0c;主要应用于人->系统交互&#xff0c;典型应用场景&#xff1a;请假&#xff0c;离职等审批 详情可见【精选】activti实际使用_activiti通过事件监听器实现的优势_记录点滴…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL

ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分&#xff1a; &#xff08;1&#xff09;PCB焊盘&#xff1a;表层的铜 &#xff0c;top层的铜 &#xff08;2&#xff09;管脚序号&#xff1a;用来关联原理图中的管脚的序号&#xff0c;原理图的序号需要和PCB封装一一…...