[系列] go-gin-api 规划目录和参数验证(二)
目录
概述
首先同步下项目概况:
上篇文章分享了,使用 go modules 初始化项目,这篇文章咱们分享:
- 规划目录结构
- 模型绑定和验证
- 自定义验证器
- 制定 API 返回结构
废话不多说,咱们开始吧。
规划目录结构
├─ go-gin-api │ ├─ app │ ├─ config //配置文件 │ ├─ config.go │ ├─ controller //控制器层 │ ├─ param_bind │ ├─ param_verify │ ├─ ... │ ├─ model //数据库ORM │ ├─ proto │ ├─ ... │ ├─ repository //数据库操作层 │ ├─ ... │ ├─ route //路由 │ ├─ middleware │ ├─ route.go │ ├─ service //业务层 │ ├─ ... │ ├─ util //工具包 │ ├─ ... │ ├─ vendor //依赖包 │ ├─ ... │ ├─ go.mod │ ├─ go.sum │ ├─ main.go //入口文件
上面的目录结构是我自定义的,大家也可以根据自己的习惯去定义。
controller 控制器层主要对提交过来的数据进行验证,然后将验证完成的数据传递给 service 处理。
在 gin 框架中,参数验证有两种:
1、模型绑定和验证。
2、自定义验证器。
其中目录
param_bind,存储的是参数绑定的数据,目录
param_verify存储的是自定义验证器。
接下来,让咱们进行简单实现。
模型绑定和验证
比如,有一个创建商品的接口,商品名称不能为空。
配置路由(route.go):
ProductRouter := engine.Group("") { // 新增产品 ProductRouter.POST("/product", product.Add) // 更新产品 ProductRouter.PUT("/product/:id", product.Edit) // 删除产品 ProductRouter.DELETE("/product/:id", product.Delete) // 获取产品详情 ProductRouter.GET("/product/:id", product.Detail) }
参数绑定(param_bind/product.go):
type ProductAdd struct { Name string `form:"name" json:"name" binding:"required"` }
控制器调用(controller/product.go):
if err := c.ShouldBind(¶m_bind.ProductAdd{}); err != nil { utilGin.Response(-1, err.Error(), nil) return }
咱们用 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)
func NameValid ( v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string, ) bool { if s, ok := field.Interface().(string); ok { if s == "admin" { return false } } return true }
参数绑定(param_bind/product.go):
type ProductAdd struct { Name string `form:"name" json:"name" binding:"required,NameValid"` }
同时还要绑定验证器:
// 绑定验证器 if v, ok := binding.Validator.Engine().(*validator.Validate); ok { v.RegisterValidation("NameValid", param_verify.NameValid) }
咱们用 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 返回结构
{ "code": 1, "msg": "", "data": null }
API 接口的返回的结构基本都是这三个字段。
比如 code=1 表示成功,code=-1 表示失败。
msg 表示提示信息。
data 表示要返回的数据。
那么,我们怎么在 gin 框架中实现它,其实很简单 基于
c.JSON()方法进行封装即可,直接看代码。
package util import "github.com/gin-gonic/gin" type Gin struct { Ctx *gin.Context } type response struct { Code int `json:"code"` Message string `json:"msg"` Data interface{} `json:"data"` } func (g *Gin)Response(code int, msg string, data interface{}) { g.Ctx.JSON(200, response{ Code : code, Message : msg, Data : data, }) return }
控制器调用(controller/product.go):
utilGin := util.Gin{Ctx:c} if err := c.ShouldBind(¶m_bind.ProductAdd{}); err != nil { utilGin.Response(-1, err.Error(), nil) return }
咱们用 Postman 模拟 post 请求时,name 参数不传或传递为空,会出现:
{ "code": -1, "msg": "Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag", "data": null }
name=admin 时:
{ "code": -1, "msg": "Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'NameValid' tag", "data": null }
OK,上面两个验证都生效了!
源码地址
https://github.com/xinliangnote/go-gin-api
go-gin-api 系列文章
- [系列] go-gin-api 路由中间件 - Jaeger 链路追踪(五)
- [系列] go-gin-api 路由中间件 - 日志记录(三)
- [系列] go-gin-api 路由中间件 - 捕获异常(四)
- golang实战使用gin+xorm搭建go语言web框架restgo详解5.6 控制器参数校验
- [毕业生的商业软件开发之路]系列文章目录规划
- 【JqGrid】API系列-参数详解
- ionic系列:$state.go()传递对象参数
- go的gin框架从请求中获取参数的方法
- 轨迹系列——验证轨迹GPS坐标转换为本地坐标的四/七参数是否准确的一种方案
- 使用validator-api来验证spring-boot的参数
- 系列 《使用sklearn进行集成学习——理论》 《使用sklearn进行集成学习——实践》 目录 1 Random Forest和Gradient Tree Boosting参数详解 2 如何调参?
- SpringMVC系列(五)使用 Serlvet 原生的 API 作为目标方法的参数
- 使用validator-api来验证spring-boot的参数
- Flask学习系列9.1—普通参数验证
- struts2系列(二):struts2参数传递错误、struts2的输入错误验证
- FileGDB API for linux学习系列之三,检索目录树
- 在gin中使用中间件实现RestAPI权限验证的示例
- springBoot系列教程06:参数验证及验证信息国际化
- Atitit 单点登录实现几种模式架构图 目录 1. 因此要点也就以下两个:存储信任验证信任 1 1.1. 共享cookie (最简单 1 1.2. 通过 url带token参数跳转 1 1.3.
- golang实战使用gin+xorm搭建go语言web框架restgo详解3 系统常用配置参数