【Golang】gin框架创建路由源码分析

golang——Gin框架及路由介绍 gin框架中采用的路由库是基于httprouter做的支持Restful风格的API,意思是"表面层状态转化",是一个互联网应用程序的API设计理念:URL定位资源。可以创建路由组,为了管理相同的URL。import ("net/http"//将应用切换到“发布模式”以提升性能//创建路由//默认使用了两个中间件Logger(),Recovery()})})//路由组1})})//路由组2})})//监听端口,默认绑定端口8080。 阅读详情

文章目录

源码分析

下面是Gin框架中登记GET、POST路由的函数实现。

// POST is a shortcut for router.Handle("POST", path, handlers).
func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes {
	return group.handle(http.MethodPost, relativePath, handlers)
}

// GET is a shortcut for router.Handle("GET", path, handlers).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
	return group.handle(http.MethodGet, relativePath, handlers)
}

使用RouterGroup类型的对象,该函数将调用的方法类型(POST、GET、PUT等)、请求路径以及其他处理函数传入handle。返回值为IRoutes类型,这是一个接口,实现了POST、GET、PUT等方法。
首先我们来看RouterGroup类型对象的生成函数。使用了一个RouterGroup生成了另一个子RouterGroup,生成时绑定了新生成的组在当前组路径上的附加路径。比如,我使用/v1组生成一个/api组,那么我访问该组路由的路径即为/v1/api/xxx。然后,还在当前组的基础上,绑定了一些处理函数(即中间件),并将之前RouterGroup与新的RouterGroup的处理函数拼接在一起。对应使用的函数下文会进行分析。

// Group creates a new router group. You should add all the routes that have common middlewares or the same path prefix.
// For example, all the routes that use a common middleware for authorization could be grouped.
func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup {
	return &RouterGroup{
		Handlers: group.combineHandlers(handlers),
		basePath: group.calculateAbsolutePath(relativePath),
		engine:   group.engine,
	}
}

接着,让我们来看处理各种路由方法的handle函数。

func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {
	absolutePath := group.calculateAbsolutePath(relativePath)
	handlers = group.combineHandlers(handlers)
	group.engine.addRoute(httpMethod, absolutePath, handlers)
	return group.returnObj()
}

其中第一个函数用于给当前传入的路径加上所在组的路径,比如当前RouterGroup为api,请求路径为/login,那么最后拼接得到的路径即为/api/login。

func (group *RouterGroup) calculateAbsolutePath(relativePath string) string {
	return joinPaths(group.basePath, relativePath)
}

// 非源码,为创建路由组的例子
apiGroup := router.Group("/api")

然后,看combineHandlers函数,传入的是一系列处理函数,返回的是HandlerChain,即一个处理函数数组。
这一步是将当前传入的handler函数与该组包含的handler函数结合,形成一个新的handler函数序列。

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

func (group *RouterGroup) combineHandlers(handlers HandlersChain) HandlersChain {
	finalSize := len(group.Handlers) + len(handlers)
	assert1(finalSize < int(abortIndex), "too many handlers")
	mergedHandlers := make(HandlersChain, finalSize)
	copy(mergedHandlers, group.Handlers)
	copy(mergedHandlers[len(group.Handlers):], handlers)
	return mergedHandlers
}

接着,handle运行了Engine下的addRoute函数。
参数分别为:
● method:请求的方法(POST、GET、PUT、DELETE等)
● path:路由的完整路径,拼接了所有父group的路径值
● handlers:路由的处理函数,拼接了所有父group的处理函数

func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
	assert1(path[0] == '/', "path must begin with '/'")
	assert1(method != "", "HTTP method can not be empty")
	assert1(len(handlers) > 0, "there must be at least one handler")

	debugPrintRoute(method, path, handlers)

	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)

	if paramsCount := countParams(path); paramsCount > engine.maxParams {
		engine.maxParams = paramsCount
	}

	if sectionsCount := countSections(path); sectionsCount > engine.maxSections {
		engine.maxSections = sectionsCount
	}
}

首先会使用assert1,判断三个条件是否满足,如不满足,则发出panic。
接着,判断当前引擎中,是否记录了method类型的方法。如果没有,则新开一个如下的结构体,专门用于记录当前引擎下存放的这类型方法。

type methodTree struct {
	method string
	root   *node
}

type node struct {
	path      string
	indices   string
	wildChild bool
	nType     nodeType
	priority  uint32
	children  []*node // child nodes, at most 1 :param style node at the end of the array
	handlers  HandlersChain
	fullPath  string
}

如果检测到当前引擎之前记录过这一类型的方法,则必将存在对应的methodTree,返回对应的node指针。
接着。执行func (n *node) addRoute(path string, handlers HandlersChain) 方法将当前路由的路径和处理函数添加到engine对应的methodTree中。addRoute函数比较复杂,有100多行,这里就不放了。感兴趣的可以前往gin包下的tree.go文件中查找阅读。值得注意的是文件的165行那个walk,相当于c++里的goto,并不是什么关键字,而是一个标签。
最后调用group.returnObj(),如下所示,返回当前的group对象。group.root是一个bool值,只有在当前engine为使用New()方法创建时才为true。也就是除了根路由组,其他子路由组的root值都为false。

func (group *RouterGroup) returnObj() IRoutes {
	if group.root {
		return group.engine
	}
	return group
}

总结

Gin在添加一个路由方法(GET、POST、PUT)时,首先结合路由所在组,获取绝对路径以及需要执行的所有函数。然后将这个路由的相关信息添加到engine并存储入一个node结构体中。

Gin源码分析(一)官方demo分析 目录:目录 简介 官方demo 1 ginDefault 11 看到New函数 12 debugPrintWARNINGNew 13 新建engine 14 分配Context 2 engineUse 21 Logger 22 recovery 23 engineUse 3 ginGET 3 routerrun 简介Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确。最近一 阅读详情

相关推荐

Golang Gin 的路由的详解

路由是 web 应用程序中的一种机制,它将到达服务器的请求与应该处理该请求的代码关联起来。简单来说,路由就是指定在访问某个 URL 时会执行的代码。Gin 使用 HTTP 方法和 URL 路径来定义路由。例如,当一个 GET 请求到达/hello路径时,该请求将被处理并返回一个响应。路由的实现原理是通过在服务器上监听传入的请求,并将其与定义的路由规则进行匹配。当请求与某个路由相匹配时,服务器将执行与该路由关联的代码,并返回响应。

canduecho的专栏 1512

Golang Gin 框架 Route学习

路由 package main import ( "github.com/gin-gonic/gin" "time" "log" ) func main() { // 初始化 router := gin.New(); // 常规操作 router.POST("/", func(context *gin.Context) { ...

Joker_Fei的博客 3460

别再瞎猜了!Fluent瞬态计算时间步长到底设多少?一个公式+实战案例搞定

本文详细解析了Fluent瞬态计算中时间步长的设置方法,通过黄金公式和实战案例,帮助工程师准确确定时间步长,避免计算发散和资源浪费。文章还介绍了动态调整策略和典型工程场景的参数优化,提升仿真效率和精度。

weixin_42638178的博客 427

【Golang】——Gin 框架中的路由与请求处理

在 Web 开发中,路由用于定义不同 URL 对应的请求处理逻辑。简单来说,路由决定了客户端发来的请求应由哪个处理函数来响应。例如,当客户端访问路径/users时,服务器会通过特定的路由配置来处理该请求并返回相应的结果。在 Gin 框架中,路由的定义非常灵活,可以通过简单的方法为不同的 URL 和 HTTP 请求方法(如 GET、POST 等)创建路由。Gin 支持路径参数、查询参数、表单参数等多种传参方式,使得处理不同请求类型变得简单直观。Gin 提供了路由分组。

Linke的博客 2184

《雷达入门课 》系列文章(5)线性调频连续波雷达基本原理(第1讲)

S=B/Tc,是调频斜率。这里的混频公式推导过程比较简单,具体的混频过程如果感兴趣可以看下面粗略的推导,混频的本质就是频谱搬移,分为上变频和下变频,一般我们用下变频,即差频信号,因此需要一个低通滤波器即可滤出我们所需要的信号。答案就是因为中频信号能够映射出目标的距离信息,换句话说就是目标的距离不一样,返回的时间τ也就不一样,因此中频信号的频率大小也就不一样,可以说距离和中频信号是成映射关系的。中频只是表示信号频段的程度词,不是表示信号的状态词,意思就是说中频是指信号的频率不是很高,正好处于中间的地位。

【调皮连续波】雷达技术领域知识博主 6025

【可穿戴算法开发】-PPG信号检测方法

文章目录一、PPG(光电容积脉搏波法)信号的检测原理二.PPG技术目前存在的问题(挑战)三. **心电信号产生的原理** 随着经济的发展,在人们生活水平提高的同时,高脂肪摄入和低运动量成为了人们普遍的生活模式,近年来高血压、高血脂已经发展为危险性最高的病症。心电、血压、血氧等生理参数是预防和分析心血管疾病的重要生理参数。 常用的心电测量仪器有:多导ECG心电图仪、PPG心率检测器、心率带等; 常...

wxq_1993的博客 2万+

gin之router

gin的是路由算法其实就是一个Trie树(也就是前缀树) 一、注册路由 1、普通注册 2、使用中间件 3、使用Group(路由组) 在预处理阶段 1、在调用中间件的时候, 是将某个路由的handler处理函数和中间件的处理函数都放在了Handlers的数组中 2、在调用Group的时候, 是将路由的path上面拼上Group的值. 也就是/user/:name, 会变成v1/user:name 最后都需要handle的addRoute注册到e...

heshushun的博客 1894

Matlab实现PSO-TCN-LSTM-Attention粒子群算法优化时间卷积长短期记忆神经网络融合注意力机制多变量时间序列预测的详细项目实例

这些数据包含了随时间变化她动态信息,具有显著她趋势她、周期她和季节她特征。该模型她核心优势在她其能够自适应地学习数据中她多层次时序信息,捕捉时间序列中她长短期依赖关系,从而提高预测她准确她和可靠她。本项目旨在实她一个基她PTO-TCN-LTTM-TFSttfntion她多变量时间序列预测模型,通过粒子群优化算法优化时间卷积长短期记忆神经网络,并融合注意力机制,提高模型她预测精度和稳定她。本项目模型她实她分为多个阶段,首先她数据预处理,接着她PTO优化,然后她TCN和LTTM网络她构建她训练。

优质创作者: 人工智能技术领域 对于有一定基础的 MATLAB和Python带具体需求都可以详谈 MATLAB和Python可以提供代码调试服务加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢 1080

Go语言web框架——Gin

Gin框架基本内容

尚墨1111的博客 8700

Dify DSL文件分享 Dify讨论群 大模型token资源等(持续收集更新)

基于LLMOps平台-Dify的一站式学习平台。包含不限于:Dify案例、DSL文件分享、模型接入、Dify交流讨论等各类资源分享。

同名公众号:dify实验室 3717

DIY T12烙铁头驱动难题:用几个电容二极管,搞定NMOS上管驱动(附Multisim仿真)

本文详细介绍了如何利用电荷泵电路解决DIY T12烙铁头驱动中的NMOS上管驱动难题。通过巧妙组合电容和二极管,构建低成本高效的升压电路,实现栅极高压驱动需求。文章包含具体电路设计、元件选型建议、实际搭建注意事项以及Multisim仿真验证,为电子爱好者提供了一套完整的解决方案。

weixin_33640562的博客 334

【golang自学之路(二)】源码分析gin框架路由注册,存储,寻找

文章目录前言Run方法注册路由路由寻找默认中间件总结我的目标 前言 学习完golang基础语法后,学习gin框架,参考李文周老师的博客进行学习。 gin框架主要分为一下二个部分 1.gin框架的路由注册 2.gin框架的中间件使用 最常见的gin框架使用如霞: package main import ( "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/",func(context *gin.Co

qq_42961251的博客 1062

(王道计算机组成原理)第二章数据的表示和运算-第三节:运算方法和运算电路 1(基本运算部件)

本文主要介绍了计算机组成原理中的加法器和算术逻辑单元(ALU)的基本概念与实现原理。首先,文章详细讲解了一位全加器的工作原理,包括其输入输出、逻辑表达式及真值表。接着,介绍了并行加法器的两种类型:串行进位和并行进位的加法器,分析了它们的优缺点。随后,文章探讨了带标志位的加法器,说明了如何通过标志位生成逻辑来判断加法结果的状态。最后,文章阐述了ALU的功能及其实现原理,包括ALU的基本结构、控制信号的作用以及在实际考试中的图示表示。通过这些内容,读者可以全面了解加法器和ALU在计算机中的重要作用及其工作原理。

快乐江湖的博客 3837

详细讲解go web框架之gin框架源码解析记录及思路流程和理解

开篇 首先gin 框架是在 官方提供的net/http标准包进行的相应封装。 那么要想理解gin框架, 就要先懂一些 net/http标准包 的相关知识。 可以参考中文的 文档: https://studygolang.com/pkgdoc 可以参考的很多文章视频等: gin源码分析流程思维导图:https://www.processon.com/view/link/5f4b70c2079129356ec5cb70#map gin源码解读 哔哩哔哩视频讲 gin源码: https://w

pythonstrat的博客 2270

QGis二次开发 —— 5.2、基于qgis搭建离线地图服务并开发雷达扫描、无人机飞行跟踪等(附:源码及工程)

QGis二次开发 —— 5.2、基于qgis搭建离线地图服务并开发雷达扫描、无人机飞行跟踪等(附:源码及工程)

225

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

golang学习之go web开发Gin框架

go web 框架 gin

weixin_56349119的博客 1147

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

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

一、大家都知道,gin框架的路由模块是采用的类似字典树的结构,存储路由与handler方法的映射。 那么,gin框架是如何将路由与handler方法进行映射的?他们的映射关系又是如何存储的呢?这篇文章主要来探讨这个问题。 二、gin初始化的过程 1、Engine的实例化 Engine是容器对象,是整个框架的基础。gin提供了两个方法来创建Engine实例,New和Default方法。 创建的Engine实例,与路由匹配相关的有RouterGroup、trees、engin.pool.New这三个参数.

qq_40229166的博客 1286

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Go语言Gin框架源码分析

gin框架使用的是定制版本的httprouter,其路由的原理是大量使用公共前缀的树结构,它基本上是一个紧凑的Trie tree(或者只是Radix Tree)。具有公共前缀的节点也共享一个公共父节点。Radix Tree基数树(Radix Tree)又称为PAT位树(Patricia Trie or crit bit tree),是一种更节省空间的前缀树(Trie Tree)。对于基数树的每个节点,如果该节点是唯一的子树的话,就和父节点合并。

ZN175623的博客 1034

golang gin框架源码分析(一)---- 下载gin框架源码 运行示例代码 由浅入深探寻原理

上面主要简单看了看 gin框架的大致结构 还是比较详细的 详略得当的把gin get 我们所做的工作给写了进去 对于通配符 以及前缀树中树的切分以及变换就没详细分析了但是经过上面的分析 其实还是能够把很多很重要的地方分析出来了感觉距离gin框架的大致把握的路在不久的将来了 下一篇可以详细看看engine的ServeHTTP中的如何使用Context这个大杀器 缓存请求消息和相应消息 以及gin对对象分配是如何缓存的。

Love 6's Private Blog 944

golang-Gin框架 源码解析

接下来又回到了 gin.go ,可以看到上面的注册入口是通过group.engine 调用的,大家不用看 routerGroup 的结构也大致猜出来了吧,其实 engine 才是真正的路由树 router,而 gin 为了实现路由组的功能,所以在外面又包了一层 routerGroup,实现路由分组,路由路径组合隔离的功能。本系列 “拆轮子系列:gin 框架” 的第一篇就到这里了,这么通读下来,发现 gin 框架的设计和实现真的太棒了,简洁清晰,又不失巧妙,很适合大家也去阅读学习一下,墙裂推荐!

S_ZaiJiangHu的博客 1430

【从源代码学习gin框架】gin框架的基本使用

当我们在浏览器键入http://localhost:8080/ping时,就会得到gin返回给前端Code StatusOK和响应文本pong!

weixin_48481972的博客 844

Gin源码解析和例子——路由

Gin是一个基于golang的net包实现的网络框架。从github上,我们可以看到它相对于其他框架而言,具有优越的性能。本系列将从应用的角度来解析其源码。(转载请指明出于breaksoftware的csdn博客) 本文我们将分析其路由的原理。先看个例子(源于github) func main() { // Disable Console Color //...

方亮的专栏 6957

【Go的Web框架源码分析】Gee和Gin的介绍及Web框架的组成部分(一)

文章目录引言1. Gee和Gin2. Web框架的组成参考 引言 今天开始阅读go的一个Web框架Gee,这是一个Go进阶的练手项目,它是仿照知名的Go开源Web框架Gin进行编写的,因此我也将结合Gin进行分析。 我们首先要搞清楚的是一个Web框架它有哪些组成部分,我们才知道我们要实现什么,怎么去实现,达到什么效果,因此本篇首先简单介绍一下Gee和Gin,然后通过查阅资料列出Web框架的组成部分以及阐述它们的作用。 1. Gee和Gin **Gin的描述** Gin is a HTTP web fra

Kaimar的博客 1682

第22关 go的web框架-gin

我们将会快速的体验到go语言下最流行的web框架之一-gin,我们除了讲解gin的基本功能以外,还会讲解gin中的一些难懂的点-中间件的原理解析。本章节的主要内容包括:gin的路由、表单验证、错误中文翻译、优雅退出等大量的细节

看花容易绣花难 996

源码分析---gin框架的http服务创建,路由注册,请求处理

当一个goroutine需要从池中获取对象时,它首先会检查local指向的poolLocal实例是否有可用的对象。否则,该goroutine会将local指向的poolLocal实例中的所有对象移动到victim中,并将local指向victim。当需要从池中获取对象时,如果池中没有可用的对象,则会调用New函数创建一个新的对象。当一个goroutine使用完一个对象时,它会将该对象返回给池。就是在group对象的handle数组中加入了当前新注册的handle,但是是通过创建新的数组替换旧的数组来做的。

IT艺术家-rookie的博客 983

Gin框架源码分析(1)—— 整体介绍

既然go原生提供了http功能,为啥还需要gin等第三方框架呢? 主要还是原生的http不满足实际业务场景的需求,gin主要提供了以下额外的功能

qq_39383767的博客 926
上一篇: 【Golang】Gin框架路由转发处理模式
下一篇: 【Golang】Gin框架中间件学习笔记
Crisp0v0
博客等级 码龄7年 124粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值