Gin源码简要分析
January 21, 2020
概述 #
通过日常对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,其中就包括了常见的:路由注册,中间件注册,路由分组,服务启动。核心概念也就是刚刚在上文提到的那四个概念。概览流程如下图:
...