golang结构体与字段验证工具插件库validator的使用
Golang结构体与字段验证工具插件库validator的使用
简介
validator是一个用于结构体和字段验证的Go语言库,它基于标签(tag)实现验证功能。该库具有以下独特特性:
- 通过验证标签或自定义验证器实现跨字段和跨结构体验证
- 支持切片、数组和映射的多层级验证
- 可以验证映射的键和值
- 处理接口类型时会先确定其底层类型
- 支持自定义字段类型如sql driver Valuer
- 验证标签别名,允许将多个验证映射到单个标签
- 可提取自定义字段名称
- 支持可定制的国际化错误消息
- 是gin框架的默认验证器
安装
使用go get安装:
go get github.com/go-playground/validator/v10
然后在代码中导入:
import "github.com/go-playground/validator/v10"
基本使用示例
下面是一个完整的示例,展示如何使用validator验证结构体字段:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// 定义一个用户结构体
type User struct {
FirstName string `validate:"required"` // 必填字段
LastName string `validate:"required"` // 必填字段
Age uint `validate:"gte=18,lte=130"` // 年龄必须在18到130之间
Email string `validate:"required,email"` // 必填且必须是有效邮箱格式
}
func main() {
// 创建验证器实例
validate := validator.New(validator.WithRequiredStructEnabled())
// 创建测试用户
user := &User{
FirstName: "John",
LastName: "Doe",
Age: 25,
Email: "john.doe@example.com",
}
// 验证结构体
err := validate.Struct(user)
if err != nil {
// 如果有错误,转换为验证错误类型
if validationErrors, ok := err.(validator.ValidationErrors); ok {
for _, fieldError := range validationErrors {
fmt.Printf("字段 %s 验证失败: %s\n", fieldError.Field(), fieldError.Tag())
}
}
return
}
fmt.Println("用户数据验证通过")
}
验证标签说明
validator支持多种验证标签,以下是一些常用标签:
字段比较
标签 | 描述 |
---|---|
eqfield | 字段等于另一个字段 |
gtfield | 字段大于另一个字段 |
gtefield | 字段大于或等于另一个字段 |
ltfield | 字段小于另一个字段 |
ltefield | 字段小于或等于另一个字段 |
nefield | 字段不等于另一个字段 |
字符串验证
标签 | 描述 |
---|---|
alpha | 仅字母 |
alphanum | 字母数字 |
contains | 包含指定字符串 |
startswith | 以指定字符串开头 |
endswith | 以指定字符串结尾 |
lowercase | 小写字母 |
uppercase | 大写字母 |
格式验证
标签 | 描述 |
---|---|
邮箱格式 | |
url | URL格式 |
uuid | UUID格式 |
datetime | 日期时间格式 |
json | JSON格式 |
base64 | Base64字符串 |
数值验证
标签 | 描述 |
---|---|
min | 最小值 |
max | 最大值 |
eq | 等于 |
gt | 大于 |
gte | 大于等于 |
lt | 小于 |
lte | 小于等于 |
其他验证
标签 | 描述 |
---|---|
required | 必填字段 |
len | 长度 |
oneof | 值必须在指定列表中 |
高级示例
嵌套结构体验证
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// 地址结构体
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Zip string `validate:"required,len=6"`
}
// 用户结构体包含嵌套地址
type User struct {
Name string `validate:"required"`
Age int `validate:"gte=18"`
Address Address `validate:"required"`
}
func main() {
validate := validator.New()
user := User{
Name: "Alice",
Age: 25,
Address: Address{
Street: "123 Main St",
City: "New York",
Zip: "10001",
},
}
err := validate.Struct(user)
if err != nil {
if validationErrors, ok := err.(validator.ValidationErrors); ok {
for _, fieldError := range validationErrors {
fmt.Printf("错误: 字段 %s 验证失败: %s\n", fieldError.Field(), fieldError.Tag())
}
}
return
}
fmt.Println("用户数据验证通过")
}
自定义验证函数
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// 自定义验证函数
func validateCountryCode(fl validator.FieldLevel) bool {
countryCode := fl.Field().String()
// 简单的国家代码验证
return countryCode == "US" || countryCode == "CN" || countryCode == "JP"
}
type User struct {
Name string `validate:"required"`
CountryCode string `validate:"required,countrycode"` // 使用自定义验证标签
}
func main() {
validate := validator.New()
// 注册自定义验证函数
_ = validate.RegisterValidation("countrycode", validateCountryCode)
user := User{
Name: "Bob",
CountryCode: "UK", // 无效的国家代码
}
err := validate.Struct(user)
if err != nil {
if validationErrors, ok := err.(validator.ValidationErrors); ok {
for _, fieldError := range validationErrors {
fmt.Printf("错误: 字段 %s 验证失败: %s\n", fieldError.Field(), fieldError.Tag())
}
}
return
}
fmt.Println("用户数据验证通过")
}
错误处理
验证函数返回error类型。如果验证失败,可以将错误转换为validator.ValidationErrors类型来获取详细的验证错误信息:
err := validate.Struct(mystruct)
if err != nil {
if validationErrors, ok := err.(validator.ValidationErrors); ok {
for _, fieldError := range validationErrors {
fmt.Printf("字段 %s 验证失败: %s\n", fieldError.Field(), fieldError.Tag())
}
}
}
性能
validator经过高度优化,性能表现优异。在MacBook Pro Max M3上的基准测试结果如下:
BenchmarkFieldSuccess-16 42461943 27.88 ns/op 0 B/op 0 allocs/op
BenchmarkFieldSuccessParallel-16 486632887 2.289 ns/op 0 B/op 0 allocs/op
BenchmarkFieldFailure-16 9566167 121.3 ns/op 200 B/op 4 allocs/op
BenchmarkFieldFailureParallel-16 17551471 83.68 ns/op 200 B/op 4 allocs/op
总结
validator是一个功能强大且灵活的Go语言验证库,适用于各种验证场景。通过结构体标签可以轻松定义验证规则,同时也支持自定义验证函数和复杂的验证逻辑。
更多关于golang结构体与字段验证工具插件库validator的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang结构体与字段验证工具插件库validator的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang结构体与字段验证工具validator使用指南
validator是Go语言中最流行的结构体字段验证库之一,它通过结构体标签(tag)定义验证规则,可以方便地对结构体字段进行各种验证。
安装validator
go get github.com/go-playground/validator/v10
基本使用
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
Name string `validate:"required,min=2,max=50"`
Email string `validate:"required,email"`
Age int `validate:"gte=18,lte=130"`
Password string `validate:"required,min=8"`
}
func main() {
validate := validator.New()
user := User{
Name: "张三",
Email: "zhangsan@example.com",
Age: 25,
Password: "12345678",
}
err := validate.Struct(user)
if err != nil {
for _, err := range err.(validator.ValidationErrors) {
fmt.Println(err.Field(), "字段验证失败:", err.Tag())
}
return
}
fmt.Println("验证通过")
}
常用验证标签
validator提供了丰富的内置验证规则:
required
- 必填字段min
- 最小长度/数值max
- 最大长度/数值len
- 固定长度/数值eq
- 等于ne
- 不等于gt
- 大于gte
- 大于等于lt
- 小于lte
- 小于等于email
- 邮箱格式url
- URL格式uuid
- UUID格式alpha
- 仅字母alphanum
- 字母和数字numeric
- 数字hexadecimal
- 十六进制contains
- 包含指定字符串excludes
- 不包含指定字符串startswith
- 以指定字符串开头endswith
- 以指定字符串结尾
自定义验证
可以注册自定义验证函数:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
Username string `validate:"required,username"`
}
func validateUsername(fl validator.FieldLevel) bool {
username := fl.Field().String()
// 自定义用户名验证逻辑
return len(username) >= 5 && len(username) <= 20
}
func main() {
validate := validator.New()
_ = validate.RegisterValidation("username", validateUsername)
user := User{Username: "user123"}
err := validate.Struct(user)
if err != nil {
fmt.Println("验证失败:", err)
return
}
fmt.Println("验证通过")
}
嵌套结构体验证
validator支持嵌套结构体的验证:
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Planet string `validate:"required"`
Phone string `validate:"required"`
}
type User struct {
Name string `validate:"required"`
Address Address `validate:"required"`
}
func main() {
validate := validator.New()
user := User{
Name: "李四",
Address: Address{
Street: "科技园路",
City: "深圳",
Planet: "地球",
Phone: "13800138000",
},
}
err := validate.Struct(user)
// 处理验证结果...
}
国际化错误消息
可以自定义错误消息:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
"gopkg.in/go-playground/validator.v9/translations/zh"
)
type User struct {
Name string `validate:"required" label:"姓名"`
Age int `validate:"gte=18" label:"年龄"`
}
func main() {
validate := validator.New()
// 注册中文翻译
zhT := zh.New()
_ = zhT.RegisterDefaultTranslations(validate)
user := User{
Name: "",
Age: 16,
}
err := validate.Struct(user)
if err != nil {
for _, err := range err.(validator.ValidationErrors) {
fmt.Println(err.Translate(zhT))
}
}
}
输出类似:
姓名为必填字段
年龄必须大于或等于18
性能考虑
validator在首次验证时会缓存结构体的验证规则,后续验证会直接从缓存中读取,因此重复验证相同结构体时性能很高。
validator是Go语言中功能强大且易于使用的验证库,通过合理使用可以大大减少业务代码中的参数校验逻辑,提高代码的可读性和可维护性。