[系列] 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 规划目录和参数验证(二)的更多相关文章
- go-gin-api 规划目录和参数验证(二)
概述 首先同步下项目概况: 上篇文章分享了,使用 go modules 初始化项目,这篇文章咱们分享: 规划目录结构 模型绑定和验证 自定义验证器 制定 API 返回结构 废话不多说,咱们开始吧. 规 ...
- .net core api 对于FromBody的参数验证
前言 在framework的mvc中,经常会使用 Model.State . ModelState.IsValid 配合着特性进行参数验证,通过这种方式可以降低controller的复杂度,使用方便. ...
- MVC之参数验证(二)
MVC内部针对这此验证是如何实现的咧???现在我们就来分析一下这此验证的背后故事.... 1.ModelValidator与ModelValidatorProvider 虽然Model绑定方式的因绑定 ...
- ASP.NET Web API 2 之参数验证
Ø 前言 目前 C# 比较流行使用 ASP.NET Web API 来承载 Web 接口,提供与客户端之间的数据交互,现在的版本已经是 2.0 了.既然是接口就少不了对输入参数的验证,所以本文主要探 ...
- Gin框架 - 项目目录
概述 今天给大家分享,在 API 端使用 Gin 框架时,项目的目录. 目录 ├─ Project Name │ ├─ config //配置文件 │ ├── ... │ ├─ controller ...
- 【quickhybrid】API规划
前言 当一切就绪后,就要开始进行API规划,这一块是整个Hybrid框架中非常重要的内容,毕竟对于前端页面来说,只会通过JS API来调用功能. 基本上,API调用起来是否方便简洁影响着整个体验. 这 ...
- 智能合约语言 Solidity 教程系列8 - Solidity API
这是Solidity教程系列文章第8篇介绍Solidity API,它们主要表现为内置的特殊的变量及函数,存在于全局命名空间里. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应 ...
- [译]C# 7系列,Part 8: in Parameters in参数
原文:https://blogs.msdn.microsoft.com/mazhou/2018/01/08/c-7-series-part-8-in-parameters/ 背景 默认情况下,方法参数 ...
- openresty开发系列11--openresty的api入门
openresty开发系列11--openresty的api入门 1)ngx_lua模块的hello world编辑nginx下conf配置文件nginx.conf# vi nginx.conf在se ...
随机推荐
- Spring Cloud 之 Gateway.
一.Gateway 和 Zuul 的区别 Zuul 基于servlet 2.5 (works with 3.x),使用阻塞API.它不支持任何长期的连接,如websocket. Gateway建立在S ...
- Java入门 面向对象第一天
面向对象 人为抽象的一种编程模型,在理解面向对象的代码时要按照抽象的模型来理解,不能只从代码字面来理解复杂的问题,学会拆分成一个一个独立的小问题,通过解决每一个小问题,最后解决一个大问题 类 类是事物 ...
- Linux系统下减少LV(逻辑卷)容量
查看文件系统现有 lv_test 容量,总计9.9G,已使用2% 命令 df -h 2 查看系统中的 PV 情况 命令:pvdisplay vg_test 下有两个 PV,分别为 /dev/sdb1 ...
- Go“一个包含nil指针的接口不是nil接口”踩坑
最近在项目中踩了一个深坑--"Golang中一个包含nil指针的接口不是nil接口",总结下分享出来,如果你不是很理解这句话,那推荐认真看下下面的示例代码,避免以后写代码时踩坑. ...
- Windbg程序调试系列-索引篇
最近整理了一下Windbg程序调试系列的文章,做个了索引贴,方便大家查询.搜索: Windbg程序调试系列1-常用命令说明&示例 Windbg程序调试系列1-Mex扩展使用总结 Windbg程 ...
- Okhttp3 网络请求框架与 Gson
Maven环境 : <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>o ...
- 后端基于方法的权限控制--Spirng-Security
后端基于方法的权限控制--Spirng-Security 默认情况下, Spring Security 并不启用方法级的安全管控. 启用方法级的管控后, 可以针对不同的方法通过注解设置不同的访问条件: ...
- Spring MVC浅入浅出——不吹牛逼不装逼
Spring MVC浅入浅出——不吹牛逼不装逼 前言 上文书说了Spring相关的知识,对Spring来了个浅入浅出,大家应该了解到,Spring在三层架构中主做Service层,那还有Web层,也就 ...
- DataPipeline丨DataOps理念与设计原则
作者:DataPipeline CEO 陈诚 上周我们探讨了数据的「资产负债表」与「现状」,期间抛给大家一个问题:如果我们制作一个企业的“数据资产负债表”,到底会有多少数据是企业真正的资产? 数据出现 ...
- 如何使用dmidecode命令查看硬件信息
引言 当我们需要获取机器硬件信息时,可使用linux系统自带的dmidecode工具进行查询. dmidecode命令通过读取系统DMI表,显示服务器硬件和BIOS信息.除了可使用dmidecode查 ...