Golang验证器之validator是使用详解
作者:yi个俗人 发布时间:2024-01-29 23:40:28
前言
对于HTTP请求,我们要在脑子里有一个根深蒂固的概念,那就是任何客户端传过来的数据都是不可信任的。那么开发接口的时候需要对客户端传提交的参数进行参数校验,如果提交的参数只有一个两个,这样我们可以简单写个if判断,那么要是有很多的参数校验,那么满屏都是参数校验的if判断,效率不仅低还不美观,接下来我们介绍一个参数校验器validator
。
什么是validator
Validator
是一个 Golang 的第三方库,用于对数据进行校验,常用于 API 的开发中,对客户端发出的请求数据进行严格校验,防止恶意请求。
安装
validator包安装:
go get -u github.com/go-playground/validator/v10
使用方法
导入validator:
import "github.com/go-playground/validator/v10"
validator 应用了 Golang
的 Struct Tag
和 Reflect
机制,基本思想是:在 Struct Tag
中为不同的字段定义各自类型的约束,然后通过 Reflect
获取这些约束的类型信息并在校验器中进行数据校验。
示例:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
UserName string `json:"user_name" validate:"required"`
Password string `json:"password" validate:"required,min=6,max=20"`
}
func main() {
example := User{
Password: "123",
}
//实例化验证器
validate := validator.New()
errs := validate.Struct(example)
if errs != nil {
for _, err := range errs.(validator.ValidationErrors) {
fmt.Println(err)
}
}
}
validator包的验证提示默认是英文的,输出如下:
这样看可能不太清楚,如果需要翻译成中文则还需安装验证提示翻译包:
go get -u github.com/go-playground/locales
go get -u github.com/go-playground/universal-translator
修改后如下:
package main
import (
"fmt"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
zh_translations "github.com/go-playground/validator/v10/translations/zh"
)
type User struct {
UserName string `json:"user_name" validate:"required"`
Password string `json:"password" validate:"required,min=6,max=20"`
}
func main() {
example := User{
Password: "123",
}
// 中文翻译器
uni := ut.New(zh.New())
trans, _ := uni.GetTranslator("zh")
//实例化验证器
validate := validator.New()
// 注册翻译器到校验器
err := zh_translations.RegisterDefaultTranslations(validate, trans)
if err!=nil {
fmt.Println(err)
return
}
errs := validate.Struct(example)
if errs != nil {
for _, err := range errs.(validator.ValidationErrors) {
fmt.Println(err.Translate(trans))
}
}
}
执行输出:
校验规则
下面列举一部分我们开发中经常用到的验证规则,详细验证规则可以参考文档:
https://pkg.go.dev/gopkg.in/go-playground/validator.v10
Tag | 说明 | 示例 |
---|---|---|
required | 必填 | Field或Struct validate:"required" |
omitempty | 空时忽略 | Field或Struct validate:"omitempty" |
len | 长度 | Field validate:"len=0" |
eq | 等于 | Field validate:"eq=0" |
gt | 大于 | Field validate:"gt=0" |
gte | 大于等于 | Field validate:"gte=0" |
lt | 小于 | Field validate:"lt=0" |
lte | 小于等于 | Field validate:"lte=0" |
min | 最小值 | Field validate:"min=1" |
max | 最大值 | Field validate:"max=2" |
required_with | 其他字段其中一个不为空且当前字段不为空 | Field validate:"required_with=Field1 Field2" |
required_without | 其他字段其中一个为空且当前字段不为空 | Field `validate:“required_without=Field1 Field2” |
lowercase | 符串值是否只包含小写字符 | Field validate:"lowercase" |
uppercase | 符串值是否只包含大写字符 | Field validate:"uppercase" |
字符串值包含一个有效的电子邮件 | Field validate:"email" | |
json | 字符串值是否为有效的JSON | Field validate:"json" |
url | 符串值是否包含有效的url | Field validate:"url" |
uri | 符串值是否包含有效的 uri | Field validate:"uri" |
contains | 字符串值包含子字符串值 | Field validate:"contains=@" |
excludes | 字符串值不包含子字符串值 | 字符串值不包含子字符串值 Field validate:"excludes=@" |
ip | 字符串值是否包含有效的 IP 地址 | Field validate:"ip" |
datetime | 字符串值是否包含有效的日期 | Field validate:"datetime" |
startswith | 字符串以提供的字符串值开始 | Field validate:"startswith=abc" |
endswith | 字符串以提供的字符串值结束 | Field validate:"endswith=abc" |
跨字段验证
validator 允许定义跨字段验证,即:验证某个字段与其他字段之间的关系。这种验证实际上分为两种:
一种是参数字段就是同一个结构体中的平级字段。
另一种是参数字段为结构中其他字段的字段。
验证语法很简单,如果是验证同一个结构中的字段,则在基础的 Tags 后面添加一个 field 后缀,例如:eqfield 定义字段间的相等(eq)约束。如果是更深层次的字段,在 field 之前还需要加上 cs(Cross-Struct),eq 就变为了 eqcsfield。
eqfield=Field:必须等于 Field 的值。
nefield=Field:必须不等于 Field 的值。
gtfield=Field:必须大于 Field 的值。
gtefield=Field: 必须大于等于 Field 的值。
ltfield=Field:必须小于 Field 的值。
ltefield=Field:必须小于等于 Field 的值。
eqcsfield=Other.Field:必须等于 struct Other 中 Field 的值。
necsfield=Other.Field:必须不等于 struct Other 中 Field 的值。
gtcsfield=Other.Field:必须大于 struct Other 中 Field 的值;
gtecsfield=Other.Field:必须大于等于 struct Other 中 Field 的值。
ltcsfield=Other.Field:必须小于 struct Other 中 Field 的值。
ltecsfield=Other.Field:必须小于等于 struct Other 中 Field 的值。
另外还有几个常用的 Tag:
required_with=Field1 Field2:在 Field1 或者 Field2 存在时,必须;
required_with_all=Field1 Field2:在 Field1 与 Field2 都存在时,必须;
required_without=Field1 Field2:在 Field1 或者 Field2 不存在时,必须;
required_without_all=Field1 Field2:在 Field1 与 Field2 都存在时,必须;
错误处理
通过看源码,我们可以看到validator 返回的错误有两种,一种是参数错误,一种是校验错误,它们都实现了 error 接口。
参数错误时,返回 InvalidValidationError 类型;
校验错误时,返回 ValidationErrors 类型。ValidationErrors 是一个错误切片,保存了每个字段违反的每个约束信息。
所以 validator 校验返回的结果有 3 种情况:
nil:没有错误;
InvalidValidationError:输入参数错误;
ValidationErrors:字段违反约束。
validator 返回的错误有两种,一种是参数错误,一种是校验错误,它们都实现了 error 接口。
参数错误时,返回 InvalidValidationError 类型;
校验错误时,返回 ValidationErrors 类型。ValidationErrors 是一个错误切片,保存了每个字段违反的每个约束信息。
所以 validator 校验返回的结果只有 3 种情况:
nil:没有错误;
InvalidValidationError:输入参数错误;
ValidationErrors:字段违反约束。
我们可以在程序中判断 err != nil
时,可以依次将 err转换为 InvalidValidationError
和 ValidationErrors
以获取更详细的信息:
err := validate.Struct(user)
if err != nil {
invalid, ok := err.(*validator.InvalidValidationError)
if ok {
fmt.Println("param error:", invalid)
return
}
validationErrs := err.(validator.ValidationErrors)
for _, validationErr := range validationErrs {
fmt.Println(validationErr)
}
}
小结
通过以上的内容我们了解了validator
一些基本的功能和用法,在我们开发中大大提高了开发效率。
validator
功能非常丰富,使用较为简单方便。它的应用非常广泛,建议了解一下。
来源:https://juejin.cn/post/7133399499418337311


猜你喜欢
- tkinter库Canvas操作三个实例实例一:涂鸦import tkinter as tkimport pyautogui as agfr
- 本文实例讲述了mysql 复制原理与实践应用。分享给大家供大家参考,具体如下:复制功能是将一个mysql数据库上的数据复到一个或多个mysq
- l当今世界,技术发展迅猛,不论是什么行业,大多数关键数据都是放置于数据库中进行管理的,一来目前数据库技术已经相当成熟,二来其管理功能非常强大
- 一、学习目标:学会利用python的GUI做界面布局手写计算器代码熟悉控件的使用方法优化计算器代码,解决 获取按钮文本 的方法了解lambd
- 表a aid adate 1 a1 2 a2 3 a3表b bid bdate 1 b1 2 b2 4 b4两个表a、b相连接,要取出id相
- 一、bs4解析import requestsfrom bs4 import BeautifulSoupimport datetimeif _
- typora使用latex进行公式的编写,下面是具体的行间公式和行内公式的快捷键方法:CTRL+SHIFT+M开启行间公式$$开启行内公式1
- 内容摘要:下面是虚机维护中,经常碰到的一些ASP程序中的数据库调用的错误,现收集整理如下:1.不能打开注册表关键字(8007000e);2.
- 这篇文章主要介绍了pyftplib中文乱码问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- 不通过数据源名DSN也能访问Access数据库吗?代码如下:<% dim conn &nbs
- 本文实例为大家分享了python实现人机五子棋的具体代码,供大家参考,具体内容如下图形界面引用PyQt5,还有socket通信。可以局域网对
- 匹配中文字符的正则表达式: [\u4e00-\u9fa5]匹配双字节字符(包括汉字在内):[^\x00-\xff]应用:计算字符串的长度(一
- 目录问题描述解决方案讨论总结问题描述怎样在数据字典中执行一些计算操作(比如求最值、排序等)?解决方案有如下字典:stocks = { &nb
- 目录一个不那么方便的解决方案:实战演练网站在线转换Postman今天介绍个神奇的网站!堪称爬虫偷懒的神器!我们在写爬虫,构建网络请求的时候,
- 浏览器的简单操作# 导入webdriver模块# 创建driver对象,指定Chrome浏览器driver = webdrive
- Django生成数据库表时报错 __init__() missing 1 required positional argument:
- input高级限制级用法1.取消按钮按下时的虚线框 在input里添加属性值 hideFocus 或者 HideFocus=true2.只读
- 遇到这样一个需求,有一张表,要给这张表新增一个字段delta,delta的值等于每行的c1列的值减去上一行c1列的值。我的解决方案,可以通过
- 用游标,和WHILE可以遍历您的查询中的每一条记录并将要求的字段传给变量进行相应的处理==================DECLARE @
- 写爬虫有一个绕不过去的问题就是验证码,现在验证码分类大概有4种:图像类滑动类点击类语音类今天先来看看图像类,这类验证码大多是数字、字母的组合