Gin源码简要分析
概述 #
通过日常对gin场景出发,深入源码,总结介绍gin的核心设计。包含:Engine / HandlerFunc / RouterGroup(Router) / Context。在日常使用中常见的就以上概念,汇总如下:
| 概念 | 解释 | 应用意义 | 
|---|---|---|
| Engine | 引擎 | web server的基础支持,也是服务的入口 和 根级数据结构 | 
| RouterGroup(Router) | 路由 | 用于支持gin,REST路由绑定和路由匹配的基础,源于radix-tree数据结构支持 | 
| HandlerFunc | 处理函数 | 逻辑处理器和中间件实现的函数签名 | 
| Context | 上下文 | 封装了请求和响应的操作,为HandlerFunc的定义和中间件模式提供支持 | 
从DEMO开始 #
type barForm struct {
    Foo string  `form:"foo" binding:"required"`
    Bar int     `form:"bar" binding:"required"`
}
func (fooHdl FooHdl) Bar(c *gin.Context) {
    var bform = new(barForm)
    if err := c.ShouldBind(bform); err != nil {
        // true: parse form error
        return
    }
    // handle biz logic and generate response structure
    // c (gin.Context) methods could called to support process-controling
    c.JSON(http.StatusOK, resp)
    // c.String() alse repsonse to client
}
// mountRouters .
func mountRouters(engi *gin.Engine) {
    // use middlewares
    engi.Use(gin.Logger())
    engi.Use(gin.Recovery())
    
    // mount routers
    group := engi.Group("/v1")
    {
        fooHdl := demohtp.New()
        group.GET("/foo", fooHdl.Bar)
        group.GET("/echo", fooHdl.Echo)
        // subGroup := group.Group("/subg")
        // subGroup.GET("/hdl1", fooHdl.SubGroupHdl1) // 最终路由:"targetURI = /v1/subg/hdl1"
    }
}
func main() {
    engi := gin.New()
    mountRouters(engi)
    if err := engi.Run(":8080"); err != nil {
        log.Fatalf("engi exit with err=%v", err)
    }
}
通过上述的代码就简单开启了一个gin server,其中就包括了常见的:路由注册,中间件注册,路由分组,服务启动。核心概念也就是刚刚在上文提到的那四个概念。概览流程如下图:
...