概述

首先同步下项目概况:

上篇文章分享了,使用 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(&param_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
}

这里我还准备了一分学习图和资料,如下:

链接:https://pan.baidu.com/s/1v5gm7n0L7TGyejCmQrMh2g 提取码:x2p5

免费分享,但是X度限制严重,如若链接失效点击链接或搜索加群 群号518475424

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(&param_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,上面两个验证都生效了!

最新文章

  1. jsp通过session传递checkbox中的值
  2. select 选项的子句
  3. Hbase split的三种方式和split的过程
  4. sql 索引 填充因子(转)
  5. iOS开发--使用NSMutableAttributedString 实现富文本
  6. ajax检测账户是否存在
  7. 对Map按key和value分别排序
  8. memcached实例(enyim.com Memcached Client)
  9. 关于IPv6
  10. 发送邮件(E-mail)方法整理合集
  11. bootstrap之Click大事
  12. Elasticsearch2.3.4使用手册(使用存储过程做增量同步的探索)
  13. k8s官网 基础知识入门教程
  14. <%: Html.DisplayNameFor与 <%: Html.DisplayFor的区别
  15. android AsyncTask异步任务(笔记)
  16. python中匿名函数lambda
  17. Leetcode 150
  18. CentOS 6.5 下源码搭建LAMP环境
  19. Python进行RSA安装加密
  20. C# 实现保留两位小数的方法

热门文章

  1. GALAXY OJ NOIP2019联合测试1-总结
  2. CHIP8模拟器的python3实现-3-指令实现
  3. JS 判断设备来源
  4. 为什么重复的GET请求变慢了?
  5. Sqlmap基础指令
  6. 使用Lambda解决_inbound_nodes错误
  7. Spring服务发现和注册
  8. 02-cmake语法-if、条件表达
  9. Maven的Scope区别笔记
  10. cmd 批处理创建 IIS 站点