为什么在微信里面打了一堆空格,键盘上的 “发送” 变成了 “换行”,右边也没有独立发送按钮
想点发送,发现按钮是灰的或者直接消失了:
为什么你打了空格,发送按钮直接没了?
这就是微信前端输入校验的典型表现:
当你输入框里只有空格(或其他不可见空白字符)时,微信会判定为「无有效内容」,直接隐藏发送按钮,根本不让你提交
Go 语言输入校验(Validation)详解
在实际开发中,用户提交的数据是不可信的。
例如:
{
"username":"admin",
"password":"123"
}
如果后端不校验:
- 用户名为空
- 密码长度不足
- 邮箱格式错误
- 年龄为负数
都会直接进入数据库;
因此:
输入校验(Validation)
是后端开发必须要做的事情
一、什么是输入校验
例如注册接口:
{
"username":"zhangsan",
"password":"123456",
"email":"123@qq.com"
}
后端需要检查:
username 是否为空
password 长度是否符合要求
email 格式是否正确
年龄是否超出范围
这个过程就叫:
输入校验
(Input Validation)
二、Gin中的输入校验
Gin已经帮我们集成好了:
github.com/go-playground/validator/v10
所以:
c.ShouldBindJSON()
不仅能绑定数据:
{
"username":"admin"
}
还能自动校验
三、最简单的例子
定义结构体:
type RegisterReq struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
接口:
func Register(c *gin.Context) {
var req RegisterReq
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{
"msg": err.Error(),
})
return
}
c.JSON(200, gin.H{
"msg": "success",
})
}
请求:
{
"username":"admin"
}
少了 password
返回:
{
"msg":"Key: 'RegisterReq.Password' Error:Field validation for 'Password' failed on the 'required' tag"
}
说明:
required
表示不能为空
四、常用校验标签
required
不能为空
type User struct {
Name string `json:"name" binding:"required"`
}
min
最小长度
type User struct {
Password string `json:"password" binding:"min=6"`
}
要求:
长度至少6位
max
最大长度
type User struct {
Username string `json:"username" binding:"max=20"`
}
要求:
最多20个字符
len
固定长度
type User struct {
Code string `json:"code" binding:"len=6"`
}
要求:
必须6位
验证码经常用。
五、数字校验
gt
大于
Age int `json:"age" binding:"gt=0"`
要求:
age > 0
gte
大于等于
Age int `json:"age" binding:"gte=18"`
要求:
age >= 18
lt
小于
Age int `json:"age" binding:"lt=100"`
要求:
age < 100
lte
小于等于
Age int `json:"age" binding:"lte=100"`
要求:
age <= 100
六、邮箱校验
type User struct {
Email string `json:"email" binding:"required,email"`
}
请求:
{
"email":"123@qq.com"
}
通过
请求:
{
"email":"abc"
}
失败
七、手机号校验
validator没有内置中国手机号规则。
一般自己写:
type User struct {
Phone string `json:"phone" binding:"required,len=11"`
}
或者:
regexp
校验。
八、多个规则同时使用
type User struct {
Username string `json:"username" binding:"required,min=3,max=20"`
}
含义:
不能为空
至少3位
最多20位
九、ShouldBindJSON干了什么
很多人只会写:
c.ShouldBindJSON(&req)
不知道发生了什么
实际上:
第一步
读取Body
{
"username":"admin",
"password":"123456"
}
第二步
根据:
json:"username"
映射字段
变成:
req.Username = "admin"
第三步
检查:
binding:"required"
第四步
检查:
binding:"min=6"
第五步
全部通过返回:
err == nil
最终:
JSON
↓
结构体
↓
binding校验
↓
成功
十、自定义校验
例如:
用户名必须以 admin 开头
Gin默认没有。
可以注册自己的规则。
validate.RegisterValidation("admin", func(fl validator.FieldLevel) bool {
value := fl.Field().String()
return strings.HasPrefix(value, "admin")
})
使用:
type User struct {
Username string `binding:"admin"`
}
十一、项目中最常见写法
type LoginReq struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required,min=6,max=20"`
}
func Login(c *gin.Context) {
var req LoginReq
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{
"msg": err.Error(),
})
return
}
// 登录逻辑
}
十二、面试高频问题
Q1:Gin如何进行参数校验?
答:
Gin底层集成了 validator 库。
通过 binding 标签定义校验规则。
调用 ShouldBindJSON 时:
先绑定JSON到结构体
再自动执行校验
Q2:required是什么意思?
binding:"required"
表示:
字段不能为空
Q3:ShouldBindJSON做了什么?
读取请求Body
JSON转结构体
执行binding规则校验
返回error
总结
ShouldBindJSON
=
JSON解析
+
结构体赋值
+
validator校验
常见标签:
required 必填 min 最小长度 max 最大长度 len 固定长度 gt 大于 gte 大于等于 lt 小于 lte 小于等于 email 邮箱格式
实际开发中最常用的组合:
binding:"required" binding:"required,min=6,max=20" binding:"required,email"