脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Golang验证器之validator是使用详解

Golang验证器之validator是使用详解

2022-11-12 12:01yi个俗人 Golang

Validator是一个 Golang 的第三方库,用于对数据进行校验,常用于 API 的开发中,对客户端发出的请求数据进行严格校验,防止恶意请求。本文通过示例详细讲解了Validator的使用,需要的可以参考一下

前言

对于HTTP请求,我们要在脑子里有一个根深蒂固的概念,那就是任何客户端传过来的数据都是不可信任的。那么开发接口的时候需要对客户端传提交的参数进行参数校验,如果提交的参数只有一个两个,这样我们可以简单写个if判断,那么要是有很多的参数校验,那么满屏都是参数校验的if判断,效率不仅低还不美观,接下来我们介绍一个参数校验器validator

什么是validator

Validator 是一个 Golang 的第三方库,用于对数据进行校验,常用于 API 的开发中,对客户端发出的请求数据进行严格校验,防止恶意请求。

安装

validator包安装:

?
1
go get -u github.com/go-playground/validator/v10

使用方法

导入validator:

?
1
import "github.com/go-playground/validator/v10"

validator 应用了 GolangStruct Tag Reflect机制,基本思想是:在 Struct Tag 中为不同的字段定义各自类型的约束,然后通过 Reflect 获取这些约束的类型信息并在校验器中进行数据校验。

示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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包的验证提示默认是英文的,输出如下:

Golang验证器之validator是使用详解

这样看可能不太清楚,如果需要翻译成中文则还需安装验证提示翻译包:

?
1
2
go get -u github.com/go-playground/locales
go get -u github.com/go-playground/universal-translator

修改后如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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))
        }
    }
 
}

执行输出:

Golang验证器之validator是使用详解

校验规则

下面列举一部分我们开发中经常用到的验证规则,详细验证规则可以参考文档:

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"
email 字符串值包含一个有效的电子邮件 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转换为 InvalidValidationErrorValidationErrors 以获取更详细的信息:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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功能非常丰富,使用较为简单方便。它的应用非常广泛,建议了解一下。

到此这篇关于Golang验证器之validator是使用详解的文章就介绍到这了,更多相关Golang validator内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7133399499418337311

延伸 · 阅读

精彩推荐
  • GolangGo语言接口的用法详解

    Go语言接口的用法详解

    本文详细讲解了Go语言接口的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    奋斗的大橙子3382022-07-13
  • GolangGo语言中并发的工作原理

    Go语言中并发的工作原理

    本文详细讲解了Go语言中并发的工作原理,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...

    奋斗的大橙子8912022-07-16
  • Golanggolang移除数组中重复的元素操作

    golang移除数组中重复的元素操作

    这篇文章主要介绍了golang移除数组中重复的元素操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    思维的深度6842021-03-17
  • GolangGo语言写入字符串到文件的方法

    Go语言写入字符串到文件的方法

    这篇文章主要介绍了Go语言写入字符串到文件的方法,实例分析了Go语言操作字符串及文本的技巧,具有一定参考借鉴价值,需要的朋友可以参考下 ...

    秋风秋雨9882020-04-19
  • GolangGo语言操作redis用法实例

    Go语言操作redis用法实例

    这篇文章主要介绍了Go语言操作redis用法,实例分析了Go语言操作redis的技巧,具有一定参考借鉴价值,需要的朋友可以参考下 ...

    niuniu3762020-04-20
  • Golanggolang fmt格式“占位符”的实例用法详解

    golang fmt格式“占位符”的实例用法详解

    在本篇文章里小编给大家整理的是一篇关于golang fmt格式“占位符”的实例用法详解内容,有兴趣的朋友们可以学习下。...

    studygolang6142021-08-13
  • GolangGo 高效截取字符串的一些思考

    Go 高效截取字符串的一些思考

    这篇文章主要介绍了Go 高效截取字符串的一些思考,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下...

    thinkeridea4162020-05-29
  • Golang聊聊Golang的语言结构和变量问题

    聊聊Golang的语言结构和变量问题

    这篇文章主要介绍了Golang的语言结构和变量问题,在golang中定义变量的一般形式是使用 var 关键字,本文通过实例代码给大家介绍的非常详细,需要的朋友可...

    曲鸟10862021-11-29