七叶笔记 » golang编程 » Golang Web框架Gin解析(三)

Golang Web框架Gin解析(三)

首先,在这里祝大家中秋快乐,阖家幸福。其次,深表歉意由于最近公司事情比较多,没有来的及写后面的学习内容。

借此节日为大家奉上第三篇学习笔记,在前面我们看了Gin的最核心的部分是自定义一个http.Handle 结构体 ,并且我们详细的看了Gin是怎么定义结构体的属性的。并且我们在上一篇中看到Gin的自定义属性中第一个属性就是组合了RouteGroup.那么今天我们就来看看这个RouteGroup到底在Gin中充当一个什么角色?

首先我们打开Gin项目中的routergroup.go的文件,首先展现在我们的面前的是两个interface{}接口定义,分别是:

1.IRouters定义了所有路由handle的方法接口

type IRoutes interface {
 Use(...HandlerFunc) IRoutes
 Handle(string, string, ...HandlerFunc) IRoutes
 Any(string, ...HandlerFunc) IRoutes
 GET(string, ...HandlerFunc) IRoutes
 POST(string, ...HandlerFunc) IRoutes
 DELETE(string, ...HandlerFunc) IRoutes
 PATCH(string, ...HandlerFunc) IRoutes
 PUT(string, ...HandlerFunc) IRoutes
 OPTIONS(string, ...HandlerFunc) IRoutes
 HEAD(string, ...HandlerFunc) IRoutes
  Static File(string, string) IRoutes
 Static(string, string) IRoutes
 StaticFS(string, http.FileSystem) IRoutes
}
 

2.IRouter定义了所有单路由或组路由的handle实现

type IRouter interface {
 IRoutes
 Group(string, ...HandlerFunc) *RouterGroup
}
 

以上的定义主要是我们定义了我们实际定义路由时可以使用的方法,并且我们可以通过这些定义快速的实现我们想要的 restful 的接口。

那么接下来我们来具体的看一下针对这两个interface{} Gin是怎么实现的。这里就有了我们的RouterGroup

type RouterGroup struct {
 Handlers HandlersChain
 basePath string
 engine *Engine
 root bool
}
 

其中

1.handles是一个Gin自定一个函数数组,这个函数就是我们在实际使用中写func a(c *gin.Context) 这就是Gin自定义HandleFunc

2.basePath 用来存储每一个分组的path如app.Group(“/user”)此时我们得到的RouterGroup就为/user

3.engine是实际的Gin框架对象

4.root 是否为根节点,前面我们说过gin对象第一个属性就组合了RouterGroup那么在Gin初始化是我们得到的Gin,app对象的root属性就为true

好,那么接下来我们看一看Gin的方法,实现主要含义。

func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
 group.Handlers =  append (group.Handlers, middleware...)
 return group.returnObj()
}
 

先看一下Use方法,Use方法使用过Gin的同学一定不陌生,我们做用户验证,做请求拦截等等,经常会使用到Use这是Gin的 中间件 方法,那么我们来看一下Use主要干了件什么事情,

我们看到Use总共就两行代码,group.Handlers=append(group.Handlers,middleware…)和一个return ,上面我们已经说过Handlers是Gin的一个自定义函数,那么我们就明白了其实Gin的中间件也就是一个Gin的自定义函数的实现。(这里我们提前透露一下,Gin在执行Handlers时,是按照数组下标以此向下执行)因此我们就可以理解中间件的方式了。

好,那么我们在来看一个GET方法的实现,在实际开发中我们经常使用

func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
 return group.handle("GET", relativePath, handlers)
}
func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {
 absolutePath := group.calculateAbsolutePath(relativePath)
 handlers = group.combineHandlers(handlers)
 group.engine.addRoute(httpMethod, absolutePath, handlers)
 return group.returnObj()
}
 

我们看到GET方法(其实RouterGroup的其它方法都是调用了这个handle方法,除静态文件相关。)是调用了一个RouterGroup的私有方法,handle那么这个方法主要是用来做什么事情呢,这中间有个addRoute容我们下回细说,今天先不展开了。主要说下原理其实addRoute将会把我们的请求地址按照层级放入到一个树中,然后当请求过来时我们会根据请求的地址访问指定的一组handlefunc。

总结

今天主要和大家分享了RouterGroup的一些方法和对象的定义并且在,在这中间我们还留下了几个细节没有深入学习,接下我将会深入的学习中间的实现并分享给大家。

1.关于Gin每次请求都是下标式请求,如何实现的?

2.关于路由注册时Gin是如何组装这些请求的并且最终实现下标式请求?

希望有深入学习过的朋友先给分享点思路。

相关文章