Gin源码分析

214 阅读2分钟
  • 举个例子

    r := gin.New() // 初始化root路由组,并赋值给eng.RouterGroup.engin
    g := r.Group("/prefix/order")
    g.Use(Logger(), Recovery()) // 应用日志中间件,panic异常恢复中间件
    g.User(UserMiddleware()) //应用自己定义的中间件
    
    // 注入post或get请求路由
    g.POST("/hello", func (ctx *gin.Context) {
        ctx.JSON(http.StatusOK, gin.H{
            "App": "hello world"
        })
    })
    
    g.GET("/mate", func (c *gin.Context) {
        c.JSON(http.StatusOk, g.H{
            "get": "yes Mate"
        })
    })
    
    if err := r.Run(":8080"); err != nil {
        panic("start error!")
    }
    
  • 顺藤摸瓜,小王在哪 - 创建Engin实例

    // Engine结构定义
    type Engine struct {
    	RouterGroup                  //路由组封装,以{prefix}为前缀的一组路由
    	RedirectTrailingSlash bool
    
    	RedirectFixedPath bool
    
    	HandleMethodNotAllowed bool
    	ForwardedByClientIP    bool
    
    	AppEngine bool
    
    	UseRawPath bool
    
    	UnescapePathValues bool
    
    	MaxMultipartMemory int64
    
    	RemoveExtraSlash bool
    
    	delims           render.Delims       // 模版解析分隔符
    	secureJSONPrefix string
    	HTMLRender       render.HTMLRender
    	FuncMap          template.FuncMap
    	allNoRoute       HandlersChain
    	allNoMethod      HandlersChain
    	noRoute          HandlersChain
    	noMethod         HandlersChain
    	pool             sync.Pool            // 获取context的pool
    	trees            methodTrees          // 路由在内存中存储的基树数据结构
    	maxParams        uint16
    }
    
    // Engin.New()
    func New() *Engine {
    	debugPrintWARNINGNew()
    	engine := &Engine{
    		RouterGroup: RouterGroup{
    			Handlers: nil,
    			basePath: "/",
    			root:     true,
    		}, // 初始化一个root路由组
    		FuncMap:                template.FuncMap{},
    		RedirectTrailingSlash:  true,
    		RedirectFixedPath:      false,
    		HandleMethodNotAllowed: false,
    		ForwardedByClientIP:    true,
    		AppEngine:              defaultAppEngine,
    		UseRawPath:             false,
    		RemoveExtraSlash:       false,
    		UnescapePathValues:     true,
    		MaxMultipartMemory:     defaultMultipartMemory,
    		trees:                  make(methodTrees, 0, 9),
    		delims:                 render.Delims{Left: "{{", Right: "}}"},
    		secureJsonPrefix:       "while(1);",
    	}
    	engine.RouterGroup.engine = engine
    	engine.pool.New = func() interface{} {
    		return engine.allocateContext()
    	} // sync.Pool初始化,注入一个gin.Context,context详见如下
    	return engine
    }
    
  • 顺藤摸瓜,小王在哪  - 创建路由组并对路由组内所以请求路由都应用中间件

    g := r.Group("/prefix/order")
    
    g.Use(gin.Logger(), gin.Recovery()) // 应用日志中间件和Recover()中间件
    
    // 中间件的应用实际上是对路由组内绑定的HandleFuncs倒叙执行一遍,只要有一个handleFunc执行失败即返回ctx.Abort()
    
  • 顺藤摸瓜,小王在哪  - 追踪请求上下文Context定义

    type Context struct {
    	writermem responseWriter  // 对http.ResponseWriter一个简单封装,加入size和status
    	Request   *http.Request
    	Writer    ResponseWriter  // 对responseWriter实例化,加入请求header,reset,write的一些操作
    
    	Params   Params           // 上下文中存储k/v的切片集合
    	handlers HandlersChain    // 请求处理器切片集合
    	index    int8
    	fullPath string
    
    	engine *Engine
    	params *Params
    
    	mu sync.RWMutex
    
    	Keys map[string]interface{}
    
    	Errors errorMsgs
    
    	Accepted []string
    
    	queryCache url.Values
    
    	formCache url.Values
    
    	sameSite http.SameSite
    }
    
  • 定义路由RouteInfo

    type RouteInfo struct {
    	Method      string      // 请求方式
    	Path        string      // 请求uri路径
    	Handler     string      // 
    	HandlerFunc HandlerFunc // 满足此路由的请求交给HandleFunc处理func(ctx *gin.Context)
    }
    
  • 处理满足路由的Http请求HandleFunc - 即gin的中间件实现函数

    type HandlerFunc func(*Context)