Maison  >  Article  >  développement back-end  >  Explication détaillée du code source de Gin Engine

Explication détaillée du code source de Gin Engine

Golang菜鸟
Golang菜鸟avant
2023-08-04 17:41:43707parcourir

Qu'est-ce que le gin ?

Gin est un framework web HTTP écrit en Go (Golang). Il possède une API de type Martini mais fonctionne 40 fois plus vite que Martini. Si vous avez besoin de performances extrêmes, utilisez Gin.

gin Pourquoi c'est rapide ?

Jetons d'abord un coup d'œil au test de référence officiel Adresse[1]

Explication détaillée du code source de Gin Engine

Ceci n'est qu'une partie de celui-ci, vous pouvez vous rendre à l'adresse ci-dessus pour voir la version complète.

Nous pouvons le constater grâce aux tests de performancesgin performances dans le traitement des requêtes est en effet meilleur que les autres (27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;">web le framework est beaucoup plus rapide . 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

Le problème de performances est principalement dû à l'utilisation de 🎜httprouter🎜🎜[2]🎜 et de httprouterUtiliser<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 (arbre de dictionnaire) en tant que structure de stockage de chemin, recherches hautes performances. 🎜🎜🎜🎜gin.Engine code source🎜
// 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
}
🎜 dans le Moteur Parmi eux, les plus importants sont ces trois domaines. 🎜

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. Explication détaillée du code source de Gin Engine
  2. Explication détaillée du code source de Gin Engine
  3. Explication détaillée du code source de Gin Engine

gin.New() 函数中我们可以看到 basePath 默认是 /Explication détaillée du code source de Gin Engine

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

Explication détaillée du code source de 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是容量不是长度哦

Explication détaillée du code source de Gin Engine

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

Explication détaillée du code source de Gin Engine

S'il n'y a pas de chemin racine correspondant à la méthode au débutnode objet, un sera créé, puis l'enregistrement de l'itinéraire correspondant sera ajouté. <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方法路由

这些注册在下面其实都是调用的同一个方法,我们接下来就要来翻开她的外衣看看里面是什么样的。Explication détaillée du code source de Gin Engine

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

Analyse globale du processus

Explication détaillée du code source de Gin EngineDansgin framework, vous pouvez principalement utiliser les méthodes d'enregistrement suivantes :
  • Le nom de la méthode de requête http correspondante (get,post,put...)
  • Groupe
Le routage de groupe réduit le remplissage des chemins
  • Any Register allhttpmethod router
  • Ces enregistrements ci-dessous sont en fait la même méthode appelée, nous le ferons ensuite. Ouvrons son manteau et voyons ce qui se passe à l'intérieur. Explication détaillée du code source de Gin Engine

    🎜Vous pouvez voir qu'ils s'appellent tousgroup.handle méthode🎜🎜🎜Jetons un œil à ce que fait cette méthode :🎜
    • Calculer le chemin de routagegroup.calculateAbsolutePath(relativePath) section >
    • group.calculateAbsolutePath(relativePath)
    • 为当前注册的路径增加中间件函数,并将注册的函数放在最后面
    • 添加到全局路由表中
    • 返回一个IRoutes接口

    combineHandlers 支持最大的函数数量为63-1个Explication détaillée du code source de Gin Engine

    Group 函数

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

    Explication détaillée du code source de Gin Engine

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

    Ajoutez une fonction middleware au chemin actuellement enregistré et placez la fonction enregistrée à la fin

    Ajoutez-la à la table de routage globale🎜 🎜Renvoyer aIRoutesInterface ul>🎜combineHandlers prend en charge un nombre maximum de fonctions de 63-1 individuelles Explication détaillée du code source de Gin Engine🎜

    Fonction de groupe

    🎜Maintenant, regardez Group, l'appel de cette méthode générera un nouveau basePath a été défini lors du regroupement, plus le chemin lors de l'enregistrement de la fonction, c'est le chemin de routage de la requête. 🎜🎜Une chose à noter est qu'après avoir pensé à utiliser ·Group· auparavant, l'enregistrement ultérieur n'a pas utilisé la valeur de retour. J'ai seulement compris comment la route enregistrée était enregistrée dans la table de routage globale après avoir lu le code source. 🎜
    Explication détaillée du code source de 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")
    }

    运行结果:

    Explication détaillée du code source de Gin Engine

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

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer