说说我个人的见解,为更好地分层,在使用gin时,我会做一些事情
首先是controller的抽象
//具体controller的信息
type controllerInfo struct {
method bool //true是get,false是post
path string//请求地址
controlFunc func(*gin.Context)//要干的事情
}
//controller的集合
type Controller struct {
controllerMap map[int]controllerInfo
}
//设置一个集合中的方法
func SetController(c *Controller, s string, f func(*gin.Context), method bool) *Controller {
c.controllerMap[len(c.controllerMap)] = controllerInfo{method, s, f}
return c
}
//新建一个集合
func NewController() *Controller {
controller := Controller{controllerMap: make(map[int]controllerInfo)}
return &controller
}
然后是router的注册
//把controller的集合注册进gin的引擎里
func SetRouter(r *gin.Engine, groupName string, controller *Controller) {
group := r.Group(groupName)
for i := 0; i <= len(controller.controllerMap)-1; i++ {
if controller.controllerMap[i].method {
group.GET(controller.controllerMap[i].path, controller.controllerMap[i].controlFunc)
} else {
group.POST(controller.controllerMap[i].path, controller.controllerMap[i].controlFunc)
}
}
}
接下来比如我们有一个具体的业务函数,就可以结合起来使用
//具体业务代码
func test(c *gin.Context) {
c.JSON(200, gin.H{"msg": "ok"})
}
func test2(c *gin.Context) {
c.JSON(200, gin.H{"msg": "okok"})
}
func main() {
r := gin.Default()
controller := NewController()
SetController(controller, "/test", test, true)
SetController(controller, "/test2", test2, true)
SetRouter(r, "/api", controller)
r.Run(":8083")
}
运行它,访问/api/test可以得到
{"msg":"ok"}
访问/api/test2可以得到
{"msg":"okok"}
如此一来可以很方便地分层
接下来是中间件的编写
//这是一个计算从此中间件开始到结束的方法
func costTime() gin.HandlerFunc {
//直接返回一个gin.HandlerFunc函数,里面是中间件的逻辑
return func(ctx *gin.Context) {
nowTime := time.Now()
ctx.Next()//这一句的作用是执行中间件链上的下一个中间件,在此之前的代码会先执行,在后的后执行
costTime := time.Since(nowTime)
fmt.Printf("costTime结果:" + costTime.String())
}
}
然后是中间件的使用
r := gin.Default()
r.Use(costTime())
非常简单,这样就算把中间件加入到执行链上了