搜索
首页后端开发GolangGin Engine源码详解

Gin Engine源码详解

Aug 04, 2023 pm 05:41 PM
gin

gin是什么?

Gin 是一个用 Go (Golang) 编写的 HTTP Web 框架。它具有类似 Martini 的 API,但性能比 Martini 快 40 倍。如果你需要极好的性能,使用 Gin 吧。

gin 为什么快?

我们先来看一下官方的基准测试 地址[1]

Gin Engine源码详解

这只是其中的一部分,完整的可以自行进入上述地址进行查看。

我们通过性能测试看得出来 gin 在处理请求的性能上确实比其他的web 框架快上不少。gin 在处理请求的性能上确实比其他的web 框架快上不少。

性能问题主要是使用 httprouter[2],而httprouter使用 Trie Tree(字典树)作为路径存储结构,具有高性能的查找。

gin.Engine 源码

// Engine is the framework's instance, it contains the muxer, middleware and configuration settings.
// Create an instance of Engine, by using New() or Default()
type Engine struct {
   RouterGroup       // 用于注册根路由组使用
    ...
    pool             sync.Pool    // 用于 gin.context 对象池
    trees            methodTrees  // 用于保存的请求路径
    ...
}

在 gin 的Engine

性能问题主要是使用 🎜httprouter🎜🎜[2]🎜,而httprouter使用 Trie Tree(字典树)作为路径存储结构,具有高性能的查找。🎜🎜🎜🎜gin.Engine 源码🎜
// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)

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

// 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
}
🎜在 gin 的Engine中,最主要的就是这3个字段。🎜

gin.RouterGroup 源码

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

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

// 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
}

RouterGroupHandlers存放的是当前分组的所有中间件,也可以说:请求到这个分组,那么Handlers 中的函数都会根据索引从小到大的按顺序执行。

basePath 就是存放这个分组的基础路由路径。可能直接解释过于抽象;我们来分析它的调用链来看:

  1. Gin Engine源码详解
  2. Gin Engine源码详解
  3. Gin Engine源码详解

gin.New() 函数中我们可以看到 basePath 默认是 /Gin Engine源码详解

而新的RouterGroup是通过Engine调用Group函数产生的;也就是我们自己的Group

Gin Engine源码详解

那么以后在这个Group注册的路径都会自动加上/user的路径。

为什么会自动添加路径,后面还会分析相关细节。

gin.methodTree 源码

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
}

type methodTree struct {
    method string
    root   *node
}

type methodTrees []methodTree

对于node的添加和查找我就不展开讲了,如果不懂的可以自行搜索字典树和查看 httprouter[3] 的实现。

我们刚刚在gin.New 函数中可以看到,trees是一个methodTree的切片,并在在初始化给了默认容量为9是容量不是长度哦

Gin Engine源码详解

addRoute 函数中可以看到trees的添加:

Gin Engine源码详解

如果开始没有对应方法的根路径node对象,就会创建一个出来,然后再去添加对应的路由注册。node对象,就会创建一个出来,然后再去添加对应的路由注册。

整体的流程分析

gin框架中,主要可以使用下面几种注册方式:

  • 对应的http请求方法的名称(get,post,put...
  • 通过Group分组路由减少路径的填写
  • 通过Any 注册所有http方法路由

这些注册在下面其实都是调用的同一个方法,我们接下来就要来翻开她的外衣看看里面是什么样的。Gin Engine源码详解

可以看到都是调用的group.handle

整体的流程分析

Gin Engine源码详解gin框架中,主要可以使用下面几种注册方式:
  • 对应的http请求方法的名称(get,post,put...
  • 通过Group分组路由减少路径的填写
  • 通过Any 注册所有http方法路由

这些注册在下面其实都是调用的同一个方法,我们接下来就要来翻开她的外衣看看里面是什么样的。Gin Engine源码详解

🎜可以看到都是调用的group.handle 方法🎜🎜🎜我们来看一下这个方法都做了哪些事情:🎜
  • 计算路由的路径group.calculateAbsolutePath(relativePath)
  • group.calculateAbsolutePath(relativePath)
  • 为当前注册的路径增加中间件函数,并将注册的函数放在最后面
  • 添加到全局路由表中
  • 返回一个IRoutes接口
  • combineHandlers 支持最大的函数数量为63-1个Gin Engine源码详解

    Group 函数

    现在来看Group的实现,通过调用这个方法会产生一个新的RouterGroup 并根据参数设置的基础路径,和全局engine实体,并把基础的中间件也复制到其中。

    Gin Engine源码详解

    使用分组路由最后也是调用group.handle方法进行注册,只是其中的basePath

    为当前注册的路径增加中间件函数,并将注册的函数放在最后面

    添加到全局路由表中🎜🎜返回一个IRoutes接口🎜combineHandlers 支持最大的函数数量为63-1个Gin Engine源码详解🎜

    Group 函数

    🎜现在来看Group的实现,通过调用这个方法会产生一个新的RouterGroup 并根据参数设置的基础路径,和全局engine实体,并把基础的中间件也复制到其中。🎜
    Gin Engine源码详解
    🎜使用分组路由最后也是调用group.handle方法进行注册,只是其中的basePath在分组的时候已经设置好了,加上注册函数时的路径,就是这个请求的路由路径。🎜🎜需要注意的一点,我之前想过使用·Group·后,它后面的注册没有使用返回值,注册的路由是怎么注册到全局路由表中的,看过源码才明白。🎜
    Gin Engine源码详解

    添加路由的时候,是获取的全局engine 实体,所以也是添加到全局路由表中的。

    最后需要注意的

    在使用注册中间件和注册路由的时候,需要注意他们注册的顺序。

    上一点错误的注册方式代码:

    package main
    
    import (
     "github.com/gin-gonic/gin"
    )
    
    func main() {
     eng := gin.New()
     eng.POST("login", func(context *gin.Context) {
      // 处理登录信息
     })
     eng.Use(gin.Logger())
    
     userGroup := eng.Group("/user")
     userGroup.GET("info", func(context *gin.Context) {
      // 参数验证
    
      // 处理逻辑
     })
    
     adminGroup := eng.Group("/admin")
     adminGroup.GET("info", func(context *gin.Context) {
      // 参数验证
    
      // 处理逻辑
     })
    
     eng.Use(gin.Recovery())
     adminGroup.PUT("info", func(context *gin.Context) {
      // 参数验证
    
      // 处理逻辑
     })
     eng.GET("logout", func(context *gin.Context) {
      // 处理登录信息
     })
     eng.Run(":8080")
    }

    运行结果:

    Gin Engine源码详解

    可以看到在注册路由之后,再注册中间件,那么前面注册过的路由是没有这个中间件的。

    以上是Gin Engine源码详解的详细内容。更多信息请关注PHP中文网其他相关文章!

    声明
    本文转载于:Golang菜鸟。如有侵权,请联系admin@php.cn删除
    使用GO编程语言构建可扩展系统使用GO编程语言构建可扩展系统Apr 25, 2025 am 12:19 AM

    goisidealforbuildingscalablesystemsduetoitssimplicity,效率和建筑物内currencysupport.1)go'scleansyntaxandaxandaxandaxandMinimalisticDesignenhanceProductivityAndRedCoductivityAndRedCuceErr.2)ItSgoroutinesAndInesAndInesAndInesAndineSandChannelsEnablenableNablenableNableNablenableFifficConcurrentscorncurrentprogragrammentworking torkermenticmminging

    有效地使用Init功能的最佳实践有效地使用Init功能的最佳实践Apr 25, 2025 am 12:18 AM

    Initfunctionsingorunautomationbeforemain()andareusefulforsettingupenvorments和InitializingVariables.usethemforsimpletasks,避免使用辅助效果,andbecautiouswithTestingTestingTestingAndLoggingTomaintAnainCodeCodeCodeClarityAndTestesto。

    INIT函数在GO软件包中的执行顺序INIT函数在GO软件包中的执行顺序Apr 25, 2025 am 12:14 AM

    goinitializespackagesintheordertheordertheyimported,thenexecutesInitFunctionswithinApcageIntheirdeFinityOrder,andfilenamesdetermineTheOrderAcractacractacrosmultiplefiles.thisprocessCanbeCanbeinepessCanbeInfleccessByendercrededBydeccredByDependenciesbetenciesbetencemendencenciesbetnependendpackages,whermayleLeadtocomplexinitialitialializizesizization

    在GO中定义和使用自定义接口在GO中定义和使用自定义接口Apr 25, 2025 am 12:09 AM

    CustomInterfacesingoarecrucialforwritingFlexible,可维护,andTestableCode.TheyEnableDevelostOverostOcusonBehaviorBeiroveration,增强ModularityAndRobustness.byDefiningMethodSigntulSignatulSigntulSignTypaterSignTyperesthattypesmustemmustemmustemmustemplement,InterfaceSallowForCodeRepodEreusaperia

    在GO中使用接口进行模拟和测试在GO中使用接口进行模拟和测试Apr 25, 2025 am 12:07 AM

    使用接口进行模拟和测试的原因是:接口允许定义合同而不指定实现方式,使得测试更加隔离和易于维护。1)接口的隐式实现使创建模拟对象变得简单,这些对象在测试中可以替代真实实现。2)使用接口可以轻松地在单元测试中替换服务的真实实现,降低测试复杂性和时间。3)接口提供的灵活性使得可以为不同测试用例更改模拟行为。4)接口有助于从一开始就设计可测试的代码,提高代码的模块化和可维护性。

    在GO中使用init进行包装初始化在GO中使用init进行包装初始化Apr 24, 2025 pm 06:25 PM

    在Go中,init函数用于包初始化。1)init函数在包初始化时自动调用,适用于初始化全局变量、设置连接和加载配置文件。2)可以有多个init函数,按文件顺序执行。3)使用时需考虑执行顺序、测试难度和性能影响。4)建议减少副作用、使用依赖注入和延迟初始化以优化init函数的使用。

    GO的选择语句:多路复用并发操作GO的选择语句:多路复用并发操作Apr 24, 2025 pm 05:21 PM

    go'SselectStatementTreamLinesConcurrentProgrambyMultiplexingOperations.1)itallowSwaitingOnMultipleChannEloperations,执行thefirstreadyone.2)theDefirstreadyone.2)thedefefcasepreventlocksbysbysbysbysbysbythoplocktrograpraproxrograpraprocrecrecectefnoopeready.3)

    GO中的高级并发技术:上下文和候补组GO中的高级并发技术:上下文和候补组Apr 24, 2025 pm 05:09 PM

    contextancandwaitgroupsarecrucialingoformanaginggoroutineseflect.1)context contextsallowsAllowsAllowsAllowsAllowsAllingCancellationAndDeadLinesAcrossapibiboundaries,确保GoroutinesCanbestoppedGrace.2)WaitGroupsSynChronizeGoroutines,确保Allimizegoroutines,确保AllizeNizeGoROutines,确保AllimizeGoroutines

    See all articles

    热AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智能驱动的应用程序,用于创建逼真的裸体照片

    AI Clothes Remover

    AI Clothes Remover

    用于从照片中去除衣服的在线人工智能工具。

    Undress AI Tool

    Undress AI Tool

    免费脱衣服图片

    Clothoff.io

    Clothoff.io

    AI脱衣机

    Video Face Swap

    Video Face Swap

    使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

    热工具

    mPDF

    mPDF

    mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

    VSCode Windows 64位 下载

    VSCode Windows 64位 下载

    微软推出的免费、功能强大的一款IDE编辑器

    SublimeText3汉化版

    SublimeText3汉化版

    中文版,非常好用

    禅工作室 13.0.1

    禅工作室 13.0.1

    功能强大的PHP集成开发环境

    ZendStudio 13.5.1 Mac

    ZendStudio 13.5.1 Mac

    功能强大的PHP集成开发环境