Heim >Backend-Entwicklung >Golang >Detaillierte Erläuterung des Gin Engine-Quellcodes

Detaillierte Erläuterung des Gin Engine-Quellcodes

Golang菜鸟
Golang菜鸟nach vorne
2023-08-04 17:41:43757Durchsuche

Was ist Gin?

Gin ist ein in Go (Golang) geschriebenes HTTP-Webframework. Es verfügt über eine Martini-ähnliche API, ist jedoch 40-mal schneller als Martini. Wenn Sie extreme Leistung benötigen, verwenden Sie Gin.

gin Warum ist es schnell?

Schauen wir uns zuerst den offiziellen Benchmark-Test an. Adresse[1]

Detaillierte Erläuterung des Gin Engine-Quellcodes

Dies ist nur ein Teil davon. Sie können zur oben genannten Adresse gehen, um die vollständige Version anzuzeigen.

Wir können dies durch Leistungstests sehengin Leistung bei der Verarbeitung von Anfragen ist in der Tat besser als andere (27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;">web Framework ist viel schneller . 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

Das Leistungsproblem ist hauptsächlich auf die Verwendung von 🎜httprouter🎜🎜[2]🎜 und httprouterVerwenden Sie<code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color : rgba( 27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;">Trie Tree (Wörterbuchbaum) als Pfadspeicherstruktur, leistungsstarke Suchvorgänge. 🎜🎜🎜🎜gin.Engine-Quellcode🎜
// 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
}
🎜 in Gins Engine Unter ihnen sind diese drei Bereiche die wichtigsten. 🎜

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. Detaillierte Erläuterung des Gin Engine-Quellcodes
  2. Detaillierte Erläuterung des Gin Engine-Quellcodes
  3. Detaillierte Erläuterung des Gin Engine-Quellcodes

gin.New() 函数中我们可以看到 basePath 默认是 /Detaillierte Erläuterung des Gin Engine-Quellcodes

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

Detaillierte Erläuterung des Gin Engine-Quellcodes

那么以后在这个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是容量不是长度哦

Detaillierte Erläuterung des Gin Engine-Quellcodes

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

Detaillierte Erläuterung des Gin Engine-Quellcodes

Wenn am Anfang kein Stammpfad vorhanden ist, der der Methode entsprichtnode Objekt, Es wird eines erstellt und dann die entsprechende Routenregistrierung hinzugefügt. <code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;">node对象,就会创建一个出来,然后再去添加对应的路由注册。

整体的流程分析

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

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

这些注册在下面其实都是调用的同一个方法,我们接下来就要来翻开她的外衣看看里面是什么样的。Detaillierte Erläuterung des Gin Engine-Quellcodes

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

Gesamtprozessanalyse

Detaillierte Erläuterung des Gin Engine-QuellcodesIngin Framework können Sie hauptsächlich die folgenden Registrierungsmethoden verwenden:
  • Der Name der entsprechenden http-Anfragemethode (get,post,put...)
  • ByGruppeGruppenrouting reduziert Pfadfüllung
  • Pass Any Alle registrieren

    Sie können sehen, dass sie alle heißengroup.handle method🎜🎜🎜Werfen wir einen Blick darauf, was diese Methode bewirkt:🎜
    • Routing-Pfad berechnen rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;">group.calculateAbsolutePath(relativePath)
section >group.calculateAbsolutePath(relativePath)
  • 为当前注册的路径增加中间件函数,并将注册的函数放在最后面
  • 添加到全局路由表中
  • 返回一个IRoutes接口
  • combineHandlers 支持最大的函数数量为63-1个Detaillierte Erläuterung des Gin Engine-Quellcodes

    Group 函数

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

    Detaillierte Erläuterung des Gin Engine-Quellcodes

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

    Fügen Sie eine Middleware-Funktion zum aktuell registrierten Pfad hinzu und fügen Sie die registrierte Funktion am Ende hinzu

    Fügen Sie sie zur globalen Routing-Tabelle hinzu🎜 🎜Return aIRoutesInterface ul>🎜combineHandlers unterstützt eine maximale Anzahl von Funktionen von 63-1 Personen Detaillierte Erläuterung des Gin Engine-Quellcodes🎜

    Gruppenfunktion

    🎜Schauen Sie sich jetzt anGroup-Implementierung, der Aufruf dieser Methode generiert einen neuen basePath wurde während der Gruppierung festgelegt, plus der Pfad bei der Registrierung der Funktion, dies ist der Anforderungsroutingpfad. 🎜🎜Zu beachten ist, dass ich, nachdem ich zuvor über die Verwendung von „Gruppe“ nachgedacht hatte, bei der nachfolgenden Registrierung den Rückgabewert nicht verwendet habe, nachdem ich den Quellcode gelesen hatte, wie die registrierte Route in der globalen Routing-Tabelle registriert wurde. 🎜
    Detaillierte Erläuterung des Gin Engine-Quellcodes

    添加路由的时候,是获取的全局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")
    }

    运行结果:

    Detaillierte Erläuterung des Gin Engine-Quellcodes

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

    Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Gin Engine-Quellcodes. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:Golang菜鸟. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen