前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Gin框架的工作过程

Gin框架的工作过程

作者头像
lin_zone
发布于 2021-08-05 08:08:36
发布于 2021-08-05 08:08:36
62300
代码可运行
举报
文章被收录于专栏:LIN_ZONELIN_ZONE
运行总次数:0
代码可运行
  1. 使用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "github.com/gin-gonic/gin"

func main() {
  // 得到 engine 对象,里面含有 RouterGroup 
    r := gin.Default()
  // 往路由的radix tree里面注册路由及对应的处理方法
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
  //如果run方法中没有填ip:port的话,默认会是 0.0.0.0:8080
    r.Run() // listen and serve on 0.0.0.0:8080
}

  1. 工作流程

  1. 主要代码解释
  • 路由注册:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 路由组
func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup {
	return &RouterGroup{
		Handlers: group.combineHandlers(handlers),
		basePath: group.calculateAbsolutePath(relativePath),
		engine:   group.engine,
	}
}

// POST 方法注册
func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes {
	return group.handle(http.MethodPost, relativePath, handlers)
}

// GET 方法注册
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
	return group.handle(http.MethodGet, relativePath, handlers)
}

// 注册路由
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()
}
// 注册路由之前,如果实在某个路由组基础上注册的,会将路由组对应的 handlers 给 加入到 要注册的路由节点
func (group *RouterGroup) combineHandlers(handlers HandlersChain) HandlersChain {
	finalSize := len(group.Handlers) + len(handlers)
	if finalSize >= int(abortIndex) {
		panic("too many handlers")
	}
	mergedHandlers := make(HandlersChain, finalSize)
	copy(mergedHandlers, group.Handlers)
	copy(mergedHandlers[len(group.Handlers):], handlers)
	return mergedHandlers
}

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


// 真正的注册路由方法的过程
// 先检测对应的method有没有对应的radix tree,然后再进行注册
func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
	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)

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

//func (n *node) addRoute方法是路由构建过程中最核心的地方--构建radix tree,这个算法会先计算出已有节点与将要插入的节点的共同前缀,然后根据两个节点与共同前缀的长度相比分三种情况(i < len(n.path)、i < len(path)、二者都满足),最终在radix tree中合适的位置插入该结点
  • 服务启动 & 请求处理:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 服务启动
func (engine *Engine) Run(addr ...string) (err error) {
 defer func() { debugPrintError(err) }()

 address := resolveAddress(addr)
 debugPrint("Listening and serving HTTP on %s\n", address)
  // 当请求进来的时候,会走 engine的 ServeHTTP 方法,具体可以看一下 golang 的 http包ListenAndServe方法的解析
 err = http.ListenAndServe(address, engine)
 return
}

// 相当于流量分发,当有请求到达时,会先经过此方法
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := engine.pool.Get().(*Context)
	c.writermem.reset(w)
	c.Request = req
	c.reset()

	engine.handleHTTPRequest(c)

	engine.pool.Put(c)
}


// func (engine *Engine) handleHTTPRequest(c *Context) 方法 从 context对象中获取到请求的method和url,然后从对应method的radix tree中查找对应路径对应的 handlers,将其赋值给context的handlers,调用context.Next 方法去执行 handlers(用户自定义的逻辑代码),自定义的方法中通过调用c.JSON 来给客户端返回json数据

// 执行用户自定义的逻辑代码
func (c *Context) Next() {
	c.index++
	for c.index < int8(len(c.handlers)) {
		c.handlers[c.index](c)
		c.index++
	}
}
  • gin中路由使用radix tree的好处
    1. 路由中可以使用类似于 :id 动态参数
    2. 路径中的相同部分只会出现在一个结点上,在一定程度上可以减少对内存的占用
    3. 查找效率高(虽然可能达不到map那种 O(1)的时间复杂度,查找复杂度最坏情况下是O(h),h为树高)
    4. 关于radix tree(基数树)的构建及查找我个人还没完全搞明白,感兴趣的朋友可以参考下面两篇文章:路由查找之Radix TreeGin的基数树路由局限及最佳实践

注:总结不易,如需转载请注明出处:https://cloud.tencent.com/developer/article/1856751

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
分享一波gin的路由算法
Gin 是用 Go 开发的一个微框架,Web框架,类似 Martinier 的 API,接口简洁,性能极高,也因为 httprouter的性能提高了 40 倍。
阿兵云原生
2023/02/16
4540
Gin框架详解
gin是一个开源的,用golang开发的web框架,https://github.com/gin-gonic/gin 地址如下。它有如下特性:
榴莲其实还可以
2019/07/19
7.4K0
Gin源码解析和例子——路由
        Gin是一个基于golang的net包实现的网络框架。从github上,我们可以看到它相对于其他框架而言,具有优越的性能。本系列将从应用的角度来解析其源码。(转载请指明出于breaksoftware的csdn博客)
方亮
2019/01/16
1.5K0
Gin框架核心源码走读
| 导语 最近考虑给SCF简单封一层web库,提供cgi的http协议处理、上下文、拦截器、html渲染等能力。很自然就想到了Gin框架,基于golang且框架比较轻量,这里简单把核心源码做个走读笔记
王昂
2020/01/25
3.1K0
Gin框架核心源码走读
Go:web框架 Gin 简介与实践
gin是用go语言开发的一个web框架,简单易用,是一个轻量级框架。Gin是Golang的一个web框架,封装优雅API友好,源码注释比较明确。借助Gin框架开发web服务,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范。
Freedom123
2024/03/29
8330
Go:web框架 Gin 简介与实践
Gin源码解析和例子——中间件(middleware)
        在《Gin源码解析和例子——路由》一文中,我们已经初识中间件。本文将继续探讨这个技术。(转载请指明出于breaksoftware的csdn博客)
方亮
2019/01/16
1K0
Gin框架源码解析【建议收藏】
Gin框架是golang的一个常用的web框架,最近一个项目中需要使用到它,所以对这个框架进行了学习。gin包非常短小精悍,不过主要包含的路由,中间件,日志都有了。我们可以追着代码思考下,这个框架是如何一步一步过来的。
码农编程进阶笔记
2021/12/15
2.4K0
Gin框架源码解析【建议收藏】
Go框架解析-Gin
今天是我golang框架阅读系列第三篇文章,今天我们主要看看gin的框架执行流程。关于golang框架生命周期源码阅读下面是我的计划:
用户1093396
2020/10/29
1.3K0
Go框架解析-Gin
Go高级之从源码分析Gin框架的函数链
Gin 是一个用 Go 语言开发的 Web 框架,提供类 Martini 的 API,并且由于GO语言的特性,然后性能更好。由于采用了httprouter库,它的性能比同类框架快了 40 倍左右。如果你需要一个高性能、高开发效率的框架,那么 Gin 就非常适合你,我很喜欢Go中文网对它的描述——晶莹剔透
言志志
2023/11/06
1.2K3
Go高级之从源码分析Gin框架的函数链
「Go框架」深入理解web框架的中间件运行机制
大家好,我是渔夫子。本号新推出「Go工具箱」系列,意在给大家分享使用go语言编写的、实用的、好玩的工具。同时了解其底层的实现原理,以便更深入地了解Go语言。
Go学堂
2023/01/31
7120
Golang Gin 实战(七)| 分组路由源代码分析
以上等等,这些路由最前面的部分/admin/是相同的,如果我们一个个写也没问题,但是不免会觉得琐碎、重复,无用劳动,那么有没有一种更好的办法来解决呢?Gin为我们提供的解决方案就是分组路由
飞雪无情
2020/02/10
1.3K0
gin源码阅读
c.Next()方法,这个方法的核心,主要是方便接入中间件(Middleware),使得代码模块化操作。
Michel_Rolle
2023/07/30
3K0
gin源码阅读
轻量级 Web 框架 Gin 结构分析
Go 语言最流行了两个轻量级 Web 框架分别是 Gin 和 Echo,这两个框架大同小异,都是插件式轻量级框架,背后都有一个开源小生态来提供各式各样的小插件,这两个框架的性能也都非常好,裸测起来跑的飞快。本节我们只讲 Gin 的实现原理和使用方法,Gin 起步比 Echo 要早,市场占有率要高一些,生态也丰富一些。
老钱
2019/03/18
4.3K0
轻量级 Web 框架 Gin 结构分析
gin 源码阅读(3) - gin 路由的实现剖析
上面两篇文章基本讲清楚了 Web Server 如何接收客户端请求,以及如何将请求流转到 gin 的逻辑。
haohongfan
2021/10/08
7900
我给 gin 提交了一行代码
这篇文章记录一次给 gin-gonic/gin[1] 提交了一行代码的经历,虽然没什么含金量,但是对我而言还是挺开心的哈哈。
gopher云原生
2021/10/18
1.3K1
【云+社区年度征文】深入浅出 Gin 生命周期
Gin 是一个用 Go (Golang) 编写的 web 框架,由于出色的性能优势而被广泛使用,这里我们就来分析下 Gin 的请求生命周期
柳公子
2020/12/15
1.3K0
【云+社区年度征文】深入浅出 Gin 生命周期
Gin路由之routes group
使用gin框架开发的时候,为了设计符合restful的接口,就得想办法使用一些比较规范容易使用的路由,今天就来介绍一下为了管理相同url的routes group。
希里安
2023/10/30
3030
Gin路由之routes group
你会高效写http服务器吗?Gin实战演练
胖sir开始捣鼓http服务器,在寻求一种高效的解决方式且高性能的解决方式...
阿兵云原生
2023/02/16
2.2K0
深入Gin框架内幕(一) 顶
Gin是一个用 Go (Golang) 编写的 web 框架。它是一个类似于martini但性能更好的API框架,不同于谢大主导的Beegoweb框架,后者更像是Python语言中的Django框架,内部包含了开发一个web程序所需的各种组件。
BGBiao
2020/02/13
1.8K0
DevOpsCamp 第 2 期作业: 《cobra - 05 子命令》 说下 cobra 命令树和 gin 路由树的实现差异
在 cobra 中, 每个 命令 都是独立的。通过 parent.AddCommand(children) 的形式进行串连。
老麦
2023/02/25
4290
DevOpsCamp 第 2 期作业: 《cobra - 05 子命令》 说下 cobra 命令树和 gin 路由树的实现差异
相关推荐
分享一波gin的路由算法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档