[系列] - go-gin-api 规划目录和参数验证(二)

2019年8月27日 216点热度 0人点赞 0条评论

概述

首先同步下项目概况:

图片

上篇文章分享了,使用 go modules 初始化项目,这篇文章咱们分享:

  • 规划目录结构

  • 模型绑定和验证

  • 自定义验证器

  • 制定 API 返回结构


废话不多说,咱们开始吧。


规划目录结构

  1. ├─ go-gin-api

  2. ├─ app

  3. ├─ config //配置文件

  4. ├─ config.go

  5. ├─ controller //控制器层

  6. ├─ param_bind

  7. ├─ param_verify

  8. ├─ ...

  9. ├─ model //数据库ORM

  10. ├─ proto

  11. ├─ ...

  12. ├─ repository //数据库操作层

  13. ├─ ...

  14. ├─ route //路由

  15. ├─ middleware

  16. ├─ route.go

  17. ├─ service //业务层

  18. ├─ ...

  19. ├─ util //工具包

  20. ├─ ...

  21. ├─ vendor //依赖包

  22. ├─ ...

  23. ├─ go.mod

  24. ├─ go.sum

  25. ├─ main.go //入口文件

上面的目录结构是我自定义的,大家也可以根据自己的习惯去定义。

controller 控制器层主要对提交过来的数据进行验证,然后将验证完成的数据传递给 service 处理。

在 gin 框架中,参数验证有两种:

1、模型绑定和验证。

2、自定义验证器。

其中目录 param_bind,存储的是参数绑定的数据,目录 param_verify 存储的是自定义验证器。

接下来,让咱们进行简单实现。

模型绑定和验证

比如,有一个创建商品的接口,商品名称不能为空。

配置路由(route.go):

  1. ProductRouter := engine.Group("")

  2. {

  3. // 新增产品

  4. ProductRouter.POST("/product", product.Add)


  5. // 更新产品

  6. ProductRouter.PUT("/product/:id", product.Edit)


  7. // 删除产品

  8. ProductRouter.DELETE("/product/:id", product.Delete)


  9. // 获取产品详情

  10. ProductRouter.GET("/product/:id", product.Detail)

  11. }

参数绑定(param_bind/product.go):

  1. type ProductAdd struct {

  2. Name string `form:"name" json:"name" binding:"required"`

  3. }

控制器调用(controller/product.go):

  1. if err := c.ShouldBind(&param_bind.ProductAdd{}); err != nil {

  2. utilGin.Response(-1, err.Error(), nil)

  3. return

  4. }

咱们用 Postman 模拟 post 请求时,name 参数不传或传递为空,会出现:

Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag

这说明使用到了参数设置的 binding:"required"

那么还能使用 binding 哪些参数,有文档吗?

有。Gin 使用 go-playground/validator.v8 进行验证,相关文档:

https://godoc.org/gopkg.in/go-playground/validator.v8

接下来,咱们实现一下自定义验证器。

自定义验证器

比如,有一个创建商品的接口,商品名称不能为空并且参数名称不能等于 admin。

类似于这种业务需求,无法 binding 现成的方法,需要我们自己写验证方法,才能实现。

自定义验证方法(param_verify/product.go)

  1. func NameValid (

  2. v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,

  3. field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,

  4. ) bool {

  5. if s, ok := field.Interface().(string); ok {

  6. if s == "admin" {

  7. return false

  8. }

  9. }

  10. return true

  11. }

参数绑定(param_bind/product.go):

  1. type ProductAdd struct {

  2. Name string `form:"name" json:"name" binding:"required,NameValid"`

  3. }

同时还要绑定验证器:

  1. // 绑定验证器

  2. if v, ok := binding.Validator.Engine().(*validator.Validate); ok {

  3. v.RegisterValidation("NameValid", param_verify.NameValid)

  4. }

咱们用 Postman 模拟 post 请求时,name 参数不传或传递为空,会出现:

Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag

name=admin 时:

Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'NameValid' tag

OK,上面两个验证都生效了!

上面的输出都是在控制台,能不能返回一个 Json 结构的数据呀?

能。接下来咱们制定 API 返回结构。

制定 API 返回结构

  1. {

  2. "code": 1,

  3. "msg": "",

  4. "data": null

  5. }

API 接口的返回的结构基本都是这三个字段。

比如 code=1 表示成功,code=-1 表示失败。

msg 表示提示信息。

data 表示返回的数据。

那么,我们怎么在 gin 框架中实现它?

其实很简单 基于 c.JSON() 方法进行封装即可,直接看代码。

  1. package util


  2. import "github.com/gin-gonic/gin"


  3. type Gin struct {

  4. Ctx *gin.Context

  5. }


  6. type response struct {

  7. Code int `json:"code"`

  8. Message string `json:"msg"`

  9. Data interface{} `json:"data"`

  10. }


  11. func (g *Gin)Response(code int, msg string, data interface{}) {

  12. g.Ctx.JSON(200, response{

  13. Code : code,

  14. Message : msg,

  15. Data : data,

  16. })

  17. return

  18. }

控制器调用(controller/product.go):

  1. utilGin := util.Gin{Ctx:c}

  2. if err := c.ShouldBind(&param_bind.ProductAdd{}); err != nil {

  3. utilGin.Response(-1, err.Error(), nil)

  4. return

  5. }

咱们用 Postman 模拟 post 请求时,name 参数不传或传递为空,会出现:

  1. {

  2. "code": -1,

  3. "msg": "Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag",

  4. "data": null

  5. }

name=admin 时:

  1. {

  2. "code": -1,

  3. "msg": "Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'NameValid' tag",

  4. "data": null

  5. }

OK,上面两个验证都生效了!

源码地址

https://github.com/xinliangnote/go-gin-api

go-gin-api 系列文章

图片

12820[系列] - go-gin-api 规划目录和参数验证(二)

root

这个人很懒,什么都没留下

文章评论