golang支持多种数据类型的可配置验证插件库ozzo-validation的使用
Golang支持多种数据类型的可配置验证插件库ozzo-validation的使用
ozzo-validation是一个Go包,提供了可配置和可扩展的数据验证功能。它具有以下特点:
- 使用常规编程结构而不是容易出错的struct标签来指定数据验证方式
- 可以验证不同类型的数据,如结构体、字符串、字节切片、切片、映射、数组等
- 只要实现了
Validatable
接口,就可以验证自定义数据类型 - 可以验证实现了
sql.Valuer
接口的数据类型(如sql.NullString
) - 可定制且格式良好的验证错误
- 支持错误代码和消息翻译
- 提供丰富的开箱即用验证规则
- 创建和使用自定义验证规则非常简单
安装
运行以下命令安装包:
go get github.com/go-ozzo/ozzo-validation
验证简单值
对于简单值(如字符串或整数),可以使用validation.Validate()
进行验证。例如:
package main
import (
"fmt"
"github.com/go-ozzo/ozzo-validation/v4"
"github.com/go-ozzo/ozzo-validation/v4/is"
)
func main() {
data := "example"
err := validation.Validate(data,
validation.Required, // 不能为空
validation.Length(5, 100), // 长度在5到100之间
is.URL, // 必须是有效的URL
)
fmt.Println(err)
// 输出:
// must be a valid URL
}
validation.Validate()
方法会按列出的顺序运行规则。如果规则失败,方法将返回相应的错误并跳过其余规则。如果值通过所有验证规则,方法将返回nil。
验证结构体
对于结构体值,通常需要检查其字段是否有效。例如,在RESTful应用程序中,可以将请求有效负载解组到结构体中,然后验证结构体字段。可以使用validation.ValidateStruct()
来实现这一目的:
type Address struct {
Street string
City string
State string
Zip string
}
func (a Address) Validate() error {
return validation.ValidateStruct(&a,
// Street不能为空,长度必须在5到50之间
validation.Field(&a.Street, validation.Required, validation.Length(5, 50)),
// City不能为空,长度必须在5到50之间
validation.Field(&a.City, validation.Required, validation.Length(5, 50)),
// State不能为空,且必须是由两个大写字母组成的字符串
validation.Field(&a.State, validation.Required, validation.Match(regexp.MustCompile("^[A-Z]{2}$"))),
// Zip不能为空,且必须是由五位数字组成的字符串
validation.Field(&a.Zip, validation.Required, validation.Match(regexp.MustCompile("^[0-9]{5}$"))),
)
}
a := Address{
Street: "123",
City: "Unknown",
State: "Virginia",
Zip: "12345",
}
err := a.Validate()
fmt.Println(err)
// 输出:
// Street: the length must be between 5 and 50; State: must be in a valid format.
验证映射(Map)
有时可能需要处理存储在映射中的动态数据而不是类型化模型。在这种情况下可以使用validation.Map()
:
c := map[string]interface{}{
"Name": "Qiang Xue",
"Email": "q",
"Address": map[string]interface{}{
"Street": "123",
"City": "Unknown",
"State": "Virginia",
"Zip": "12345",
},
}
err := validation.Validate(c,
validation.Map(
// Name不能为空,长度必须在5到20之间
validation.Key("Name", validation.Required, validation.Length(5, 20)),
// Email不能为空,且必须是有效的电子邮件格式
validation.Key("Email", validation.Required, is.Email),
// 使用自己的验证规则验证Address
validation.Key("Address", validation.Map(
// Street不能为空,长度必须在5到50之间
validation.Key("Street", validation.Required, validation.Length(5, 50)),
// City不能为空,长度必须在5到50之间
validation.Key("City", validation.Required, validation.Length(5, 50)),
// State不能为空,且必须是由两个大写字母组成的字符串
validation.Key("State", validation.Required, validation.Match(regexp.MustCompile("^[A-Z]{2}$"))),
// Zip不能为空,且必须是由五位数字组成的字符串
validation.Key("Zip", validation.Required, validation.Match(regexp.MustCompile("^[0-9]{5}$"))),
)),
),
)
fmt.Println(err)
// 输出:
// Address: (State: must be in a valid format; Street: the length must be between 5 and 50.); Email: must be a valid email address.
自定义错误消息
所有内置验证规则都允许自定义错误消息。只需调用规则的Error()
方法即可:
data := "2123"
err := validation.Validate(data,
validation.Required.Error("is required"),
validation.Match(regexp.MustCompile("^[0-9]{5}$")).Error("must be a string with five digits"),
)
fmt.Println(err)
// 输出:
// must be a string with five digits
创建自定义规则
创建自定义规则非常简单,只需实现validation.Rule
接口:
func checkAbc(value interface{}) error {
s, _ := value.(string)
if s != "abc" {
return errors.New("must be abc")
}
return nil
}
err := validation.Validate("xyz", validation.By(checkAbc))
fmt.Println(err)
// 输出: must be abc
如果验证函数需要额外参数,可以使用闭包技巧:
func stringEquals(str string) validation.RuleFunc {
return func(value interface{}) error {
s, _ := value.(string)
if s != str {
return errors.New("unexpected string")
}
return nil
}
}
err := validation.Validate("xyz", validation.By(stringEquals("abc")))
fmt.Println(err)
// 输出: unexpected string
规则组
当多个地方使用多个规则的组合时,可以使用以下技巧创建规则组,使代码更易于维护:
var NameRule = []validation.Rule{
validation.Required,
validation.Length(5, 20),
}
type User struct {
FirstName string
LastName string
}
func (u User) Validate() error {
return validation.ValidateStruct(&u,
validation.Field(&u.FirstName, NameRule...),
validation.Field(&u.LastName, NameRule...),
)
}
内置验证规则
validation
包提供以下规则:
In(...interface{})
: 检查值是否可以在给定的值列表中找到NotIn(...interface{})
: 检查值是否不在给定的值列表中Length(min, max int)
: 检查值的长度是否在指定范围内RuneLength(min, max int)
: 检查字符串的rune长度是否在指定范围内Min(min interface{})
和Max(max interface{})
: 检查值是否在指定范围内Match(*regexp.Regexp)
: 检查值是否匹配指定的正则表达式Date(layout string)
: 检查字符串值是否是具有指定格式的日期Required
: 检查值是否不为空(既不是nil也不是零)NotNil
: 检查指针值是否为nilNilOrNotEmpty
: 检查值是否为nil指针或非空值Nil
: 检查值是否为nil指针Empty
: 检查值是否为空Skip
: 特殊规则,表示应跳过它后面的所有规则MultipleOf
: 检查值是否为指定范围的倍数Each(rules ...Rule)
: 使用其他规则检查可迭代对象(map/slice/array)中的元素When(condition, rules ...Rule)
: 仅在条件为true时使用指定规则进行验证Else(rules ...Rule)
: 必须与When(condition, rules ...Rule)
一起使用,仅在条件为false时使用指定规则进行验证
is
子包提供了一系列常用的字符串验证规则,可以检查值的格式是否满足某些要求。
更多关于golang支持多种数据类型的可配置验证插件库ozzo-validation的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang支持多种数据类型的可配置验证插件库ozzo-validation的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
ozzo-validation:Golang 数据验证库使用指南
ozzo-validation 是一个功能强大且灵活的 Golang 数据验证库,支持多种数据类型的验证。下面我将详细介绍它的使用方法和示例代码。
安装
go get github.com/go-ozzo/ozzo-validation
go get github.com/go-ozzo/ozzo-validation/is
基本使用
1. 简单字段验证
package main
import (
"fmt"
"github.com/go-ozzo/ozzo-validation"
"github.com/go-ozzo/ozzo-validation/is"
)
func main() {
data := "example@email.com"
err := validation.Validate(data,
validation.Required, // 不能为空
validation.Length(5, 100), // 长度在5-100之间
is.Email, // 必须是邮箱格式
)
if err != nil {
fmt.Println("验证失败:", err)
} else {
fmt.Println("验证通过")
}
}
2. 结构体验证
type User struct {
Name string
Age int
Email string
Password string
}
func (u User) Validate() error {
return validation.ValidateStruct(&u,
// Name不能为空,长度在2-50之间
validation.Field(&u.Name, validation.Required, validation.Length(2, 50)),
// Age必须大于0,小于150
validation.Field(&u.Age, validation.Required, validation.Min(0), validation.Max(150)),
// Email必须符合邮箱格式
validation.Field(&u.Email, validation.Required, is.Email),
// Password长度至少6个字符
validation.Field(&u.Password, validation.Required, validation.Length(6, 0)),
)
}
func main() {
user := User{
Name: "John",
Age: 30,
Email: "john@example.com",
Password: "123456",
}
if err := user.Validate(); err != nil {
fmt.Println("验证失败:", err)
} else {
fmt.Println("验证通过")
}
}
高级功能
1. 自定义验证规则
func isAdmin(value interface{}) error {
s, _ := value.(string)
if s != "admin" {
return fmt.Errorf("必须是admin")
}
return nil
}
func main() {
username := "user"
err := validation.Validate(username,
validation.Required,
validation.By(isAdmin),
)
if err != nil {
fmt.Println("验证失败:", err)
}
}
2. 条件验证
type Order struct {
PaymentMethod string
CreditCard string
}
func (o Order) Validate() error {
return validation.ValidateStruct(&o,
validation.Field(&o.PaymentMethod, validation.Required, validation.In("credit", "paypal")),
// 只有当PaymentMethod为credit时才验证CreditCard
validation.Field(&o.CreditCard,
validation.When(o.PaymentMethod == "credit", validation.Required, validation.Length(16, 16)),
),
)
}
3. 切片验证
func main() {
names := []string{"Alice", "Bob", ""}
err := validation.Validate(names,
validation.Required, // 切片本身不能为nil
validation.Length(1, 10), // 切片长度限制
validation.Each( // 对每个元素验证
validation.Required, // 每个元素不能为空
validation.Length(2, 50), // 每个元素长度限制
),
)
if err != nil {
fmt.Println("验证失败:", err)
}
}
4. Map验证
func main() {
data := map[string]interface{}{
"name": "John",
"age": 30,
"email": "john@example.com",
}
rules := validation.Map(
validation.Key("name", validation.Required, validation.Length(2, 50)),
validation.Key("age", validation.Required, validation.Min(0), validation.Max(150)),
validation.Key("email", validation.Required, is.Email),
)
err := validation.Validate(data, rules)
if err != nil {
fmt.Println("验证失败:", err)
}
}
内置验证器
ozzo-validation 提供了丰富的内置验证器:
-
通用验证器:
Required
- 值不能为零值NotNil
- 值不能为nilIn
- 值必须在指定范围内Match
- 值必须匹配正则表达式
-
字符串验证器:
Length
- 长度限制RuneLength
- Unicode字符长度限制Date
- 必须是日期格式
-
数值验证器:
Min
- 最小值Max
- 最大值Range
- 数值范围
-
is
包提供的验证器:is.Email
- 邮箱格式is.URL
- URL格式is.IPv4
- IPv4地址is.HexColor
- 十六进制颜色代码
错误处理
func main() {
user := User{
Name: "", // 空名字
Age: 200, // 年龄过大
Email: "invalid-email",
Password: "123",
}
if err := user.Validate(); err != nil {
if e, ok := err.(validation.Errors); ok {
for field, fieldErr := range e {
fmt.Printf("%s: %v\n", field, fieldErr)
}
} else {
fmt.Println("验证失败:", err)
}
}
}
ozzo-validation 是一个功能全面且灵活的验证库,适用于各种数据验证场景。通过组合内置验证器和自定义验证规则,可以轻松实现复杂的验证逻辑。