gin context和官方context_一种代码低耦合、低冗余并且高效率的Gin开发方式。

之前简单的利用了反射功能解决了gin每次都要手动添加路由的麻烦,然后写了个开源的工具ginHelper:

https://github.com/CCChieh/ginHelper​github.com

在之后的开发中又发现每次写gin的handler的时候总是有很多的代码的重复工作,所以这次我又把handler进一步处理,这样每次可以自动生成handlerFunc避免重复的工作,使得handler最终简化成:

func (h *Helper) HelloHandler() (r *ginHelper.Router) {
	return &ginHelper.Router{
		Param:  new(service.Hello), //所需要的参数
		Path:   "/",                //路由路径
		Method: "GET",              //方法
	}
}

只需要几行便可以定义一个api,

ginHelper

ginHelper支持的功能:

  • 利用反射自动检索某一包内所有的HandlerFunc(即gin的Handler)添加到Gin的路由中。
  • 引入parameter接口的概念,通过定义实现该接口的结构体后可以自动生成一个gin.HandlerFunc,利用该特点可以极大地降低handler和service的代码重复。

一个简单的示例在

https://github.com/CCChieh/ginHelper_example​github.com

自动检索包下的handler

  1. 在存放handlerFunc的文件夹中任意位置写下 go type helper struct { }
  2. 之后每次写handlerFunc的时候都类似下方的helloHandler前面加上一个*helper的一个方法HelloHandler()中设置路由。
func (h *Helper) HelloHandler() (r *ginHelper.Router) {
    handler := func(c *gin.Context) {
        c.String(http.StatusOK, "Hello world!")
    }
    return &ginHelper.Router{
        Path:   "/HelloHandler",
        Method: "GET",
        Handlers: []gin.HandlerFunc{
            handler,
        },
    }
}

parameter接口

parameter接口的定义

type parameter interface {
    Error() error                     //错误返回
    BeforeBind(c *gin.Context)        //绑定参数前的操作
    Bind(c *gin.Context, p parameter) //绑定参数
    AfterBind(c *gin.Context)         //绑定参数后操作
    Service()                         //执行具体业务
    Result(c *gin.Context)            //结果返回
}

具体执行的流程:

816e29713ef29008eb86d3461db5eea8.png

ginHelper中内置的Param结构体

ginHelper中实现了一个最基本的parameter接口的Param结构体:

type Param struct {
    Err error //存储内部产生的错误
    Ret interface{} //存储返回的结构体
}

func (param *Param) BeforeBind(c *gin.Context) {
}

func (param *Param) AfterBind(c *gin.Context) {
}

func (param *Param) Error() error {
    return param.Err
}

func (param *Param) Bind(c *gin.Context, p parameter) {
    param.Err = c.ShouldBind(p)
}

func (param *Param) Service() {
}

func (param *Param) Result(c *gin.Context) {
    if param.Err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"message": param.Err.Error()})
    } else {
        c.JSON(http.StatusOK, param.Ret)
    }
}

使用parameter接口实现handler以及service

  1. 自定义一个参数结构体

这里自定义一个Hello结构体,引用结构体ginHelper.Param之后 重写Service方法。

type Hello struct {
	ginHelper.Param
	Name      string `form:"name" binding:"required"`
}

func (param *Hello) Service() {
	ginHelper.Ret = gin.H{"message": "Hello " + param.Name + "!"}
}

注意这里Name的tag使用参考gin的模型绑定和验证,对于其他方法参见parameter接口,可以重写该接口的所有方法来实现自定义。

当然也可以不使用ginHelper.Param自己实现parameter接口的所有方法。可以根据自己的需求选择不同的方式。

  1. 进一步简化HelloHandler()

在引进了parameter接口后HelloHandler()将被进一步简化为:

func (h *Helper) HelloHandler() (r *ginHelper.Router) {
	return &ginHeXlper.Router{
		Param:  new(service.Hello),
		Path:   "/",
		Method: "GET",
	}
}
  1. 使用中间件

这里内置了个变量ginHelper.GenHandlerFunc其值为nil,可以用来表示将会自动生成的handler,所以在使用中间件后的形式可以为:

func (h *Helper) AdminHandler() (r *ginHelper.Router) {
	return &ginHelper.Router{
		Param:  new(service.Hello),
		Path:   "/admin",
		Method: "GET",
		Handlers: []gin.HandlerFunc{
			middleware.AdminMiddleware(),
			ginHelper.GenHandlerFunc,
		},
	}
}

middleware.AdminMiddleware()是一个身份验证的中间件,这样子就可以定义中间件和自动生成的handler之间的顺序关系,当然如果默认自动生成的handler放到最后的话,写法还可以省略为:

func (h *Helper) AdminHandler() (r *ginHelper.Router) {
	return &ginHelper.Router{
		Param:  new(service.Hello),
		Path:   "/admin",
		Method: "GET",
		Handlers: []gin.HandlerFunc{
			middleware.AdminMiddleware(),
		},
	}
}

使用ginHelper自动构建路由

在运行gin的时候

r := gin.New()

自动导入handler包中的所有路由

ginHelper.Build(new(handler.Helper), r)

将user包中所有的路由导入到同一个路由组中

ginHelper.Build(new(user.Helper), r.Group("/user"))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值