golang通过结构体标签验证用户输入数据插件库checker的使用
Golang通过结构体标签验证用户输入数据插件库checker的使用
Checker是一个轻量级的Go库,用于高效验证用户输入。它支持验证结构体字段和单个输入值。
安装
使用以下命令安装Checker库:
go get github.com/cinar/checker/v2
然后在代码中导入:
import (
checker "github.com/cinar/checker/v2"
)
基本用法
验证结构体中的用户输入
Checker可以通过在结构体标签中列出检查器来验证存储在结构体中的用户输入:
type Person struct {
Name string `checkers:"trim required"`
}
person := &Person{
Name: " Onur Cinar ",
}
errors, valid := checker.CheckStruct(person)
if !valid {
// 处理验证错误
}
验证单个用户输入
你可以直接调用检查器函数来验证单个用户输入:
name := " Onur Cinar "
name, err := checker.Check(name, checker.Trim, checker.Required)
if err != nil {
// 处理验证错误
}
或者使用配置字符串:
name := " Onur Cinar "
name, err := checker.CheckWithConfig(name, "trim required")
if err != nil {
// 处理验证错误
}
简单验证
对于更简单的验证,你可以调用单个检查器函数:
name := "Onur Cinar"
err := checker.IsRequired(name)
if err != nil {
// 处理验证错误
}
检查器和标准化器
检查器验证用户输入,而标准化器将其转换为首选格式。例如,标准化器可以修剪字符串中的空格或将其转换为标题大小写。
type Person struct {
Name string `checkers:"trim required"`
}
提供的检查器
ascii
: 确保字符串仅包含ASCII字符alphanumeric
: 确保字符串仅包含字母和数字credit-card
: 确保字符串是有效的信用卡号cidr
: 确保字符串是有效的CIDR表示法digits
: 确保字符串仅包含数字email
: 确保字符串是有效的电子邮件地址fqdn
: 确保字符串是有效的完全限定域名gte
: 确保值大于或等于指定数字hex
: 确保字符串仅包含十六进制数字ip
: 确保字符串是有效的IP地址ipv4
: 确保字符串是有效的IPv4地址ipv6
: 确保字符串是有效的IPv6地址isbn
: 确保字符串是有效的ISBNlte
: 确保值小于或等于指定数字luhn
: 确保字符串是有效的LUHN号码mac
: 确保字符串是有效的MAC地址max-len
: 确保给定值(字符串、切片或映射)的长度最多为nmin-len
: 确保给定值(字符串、切片或映射)的长度至少为nrequired
: 确保提供了值regexp
: 确保字符串匹配模式time
: 确保字符串匹配提供的时间布局url
: 确保字符串是有效的URL
提供的标准化器
lower
: 将字符串转换为小写title
: 将字符串转换为标题大小写trim-left
: 从字符串左侧修剪空白trim-right
: 从字符串右侧修剪空白trim
: 从字符串两侧修剪空白upper
: 将字符串转换为大写html-escape
: 转义字符串中的特殊字符以用于HTMLhtml-unescape
: 取消转义字符串中的特殊字符以用于HTMLurl-escape
: 转义字符串中的特殊字符以用于URLurl-unescape
: 取消转义字符串中的特殊字符以用于URL
自定义检查器和标准化器
你可以定义自定义检查器或标准化器并注册它们以供在验证逻辑中使用:
checker.RegisterMaker("is-fruit", func(params string) v2.CheckFunc[reflect.Value] {
return func(value reflect.Value) (reflect.Value, error) {
stringValue := value.Interface().(string)
if stringValue == "apple" || stringValue == "banana" {
return value, nil
}
return value, v2.NewCheckError("NOT_FRUIT")
}
})
注册后,你可以在结构体标签中使用自定义检查器:
type Item struct {
Name string `checkers:"is-fruit"`
}
item := &Item{
Name: "banana",
}
errors, valid := v2.CheckStruct(item)
if !valid {
fmt.Println(errors)
}
切片和项目级检查器
当向切片添加检查器结构标签时,可以使用@
前缀表示检查器应应用于切片本身。没有@
前缀的检查器将应用于切片中的各个项目:
type Person struct {
Name string `checkers:"required"`
Emails []string `checkers:"@max-len:2 max-len:64"`
}
在这个例子中:
@max-len:2
确保Emails
切片本身最多有两个项目max-len:64
确保Emails
切片中的每个电子邮件字符串的最大长度为64个字符
本地化错误消息
当验证失败时,Checker会返回一个错误。默认情况下,Error()
函数提供en-US
语言环境的人类可读错误消息。
_, err := checker.IsEmail("abcd")
if err != nil {
fmt.Println(err)
// 输出: Not a valid email address.
}
要获取其他语言的错误消息,可以使用ErrorWithLocale()
函数。默认情况下,只注册了en-US
。你可以通过调用RegisterLocale
来注册其他语言。
// 注册de-DE本地化错误消息
checker.RegisterLocale(locales.DeDE, locales.DeDEMessages)
_, err := checker.IsEmail("abcd")
if err != nil {
fmt.Println(err.ErrorWithLocale(locales.DeDE))
// 输出: Keine gültige E-Mail-Adresse.
}
你还可以自定义现有错误消息或向locales.EnUSMessages
和其他语言环境映射添加新消息。
// 为自定义NOT_FRUIT错误代码注册en-US本地化错误消息
locales.EnUSMessages["NOT_FRUIT"] = "Not a fruit name."
errors, valid := v2.CheckStruct(item)
if !valid {
fmt.Println(errors)
// 输出: map[Name:Not a fruit name.]
}
错误消息是使用Golang模板函数生成的,允许它们包含变量。
// 包含项目名称的自定义检查器错误
err := checker.NewCheckErrorWithData(
"NOT_FRUIT",
map[string]interface{}{
"name": "abcd",
},
)
// 为自定义NOT_FRUIT错误代码注册en-US本地化错误消息
locales.EnUSMessages["NOT_FRUIT"] = "Name {{ .name }} is not a fruit name."
errors, valid := v2.CheckStruct(item)
if !valid {
fmt.Println(errors)
// 输出: map[Name:Name abcd is not a fruit name.]
}
许可证
该库可以自由使用、修改和分发,遵循MIT许可证的条款。完整的许可证文本可以在LICENSE文件中找到。
更多关于golang通过结构体标签验证用户输入数据插件库checker的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang通过结构体标签验证用户输入数据插件库checker的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 结构体标签验证:checker 库使用指南
在 Go 语言中,我们可以使用结构体标签 (struct tags) 来声明式地验证用户输入数据。checker 是一个轻量级的数据验证库,它允许我们通过结构体标签定义验证规则。
安装 checker
首先安装 checker 库:
go get github.com/bingoohuang/valid
基本使用示例
package main
import (
"fmt"
"github.com/bingoohuang/valid"
)
type User struct {
Username string `valid:"required,min=3,max=20"` // 必填,长度3-20
Email string `valid:"required,email"` // 必填,必须是邮箱格式
Age int `valid:"required,min=18,max=99"` // 必填,18-99岁
Password string `valid:"required,min=8"` // 必填,至少8位
}
func main() {
user := User{
Username: "john",
Email: "john@example.com",
Age: 25,
Password: "12345678",
}
// 验证结构体
if ok, err := valid.Check(user); !ok {
fmt.Println("验证失败:", err)
return
}
fmt.Println("验证通过!")
}
支持的验证规则
checker 支持多种验证规则:
-
必填验证
required
- 字段不能为零值
-
字符串验证
min=5
- 最小长度5max=20
- 最大长度20len=10
- 长度必须为10alpha
- 只包含字母alphanum
- 只包含字母和数字numeric
- 必须是数字email
- 必须是邮箱格式ip
- 必须是IP地址url
- 必须是URL
-
数值验证
min=18
- 最小值18max=100
- 最大值100range=18-100
- 范围18-100
-
自定义正则
regexp=^[a-zA-Z0-9]+$
- 自定义正则表达式
高级用法
自定义错误消息
type User struct {
Username string `valid:"required,min=3,max=20" msg:"用户名必填且长度3-20"`
Email string `valid:"required,email" msg:"邮箱必填且格式正确"`
}
嵌套结构体验证
type Address struct {
City string `valid:"required"`
Country string `valid:"required"`
}
type User struct {
Name string `valid:"required"`
Address Address `valid:"required"`
}
切片验证
type User struct {
Skills []string `valid:"required,min=1,max=5"` // 必须有1-5个技能
}
自定义验证函数
type User struct {
Birthday string `valid:"required,customBirthday"`
}
// 注册自定义验证函数
func init() {
valid.RegisterValidation("customBirthday", func(v interface{}, param string) bool {
dateStr, ok := v.(string)
if !ok {
return false
}
_, err := time.Parse("2006-01-02", dateStr)
return err == nil
})
}
完整示例
package main
import (
"fmt"
"github.com/bingoohuang/valid"
"time"
)
type User struct {
Username string `valid:"required,min=3,max=20" msg:"用户名必填且长度3-20"`
Email string `valid:"required,email" msg:"邮箱必填且格式正确"`
Age int `valid:"required,min=18,max=99" msg:"年龄必填且18-99岁"`
Password string `valid:"required,min=8" msg:"密码必填且至少8位"`
Birthday string `valid:"required,customBirthday" msg:"生日必填且格式为YYYY-MM-DD"`
Interests []string `valid:"required,min=1,max=5" msg:"兴趣必填且1-5个"`
Address Address `valid:"required"`
}
type Address struct {
City string `valid:"required" msg:"城市必填"`
Country string `valid:"required" msg:"国家必填"`
}
func init() {
valid.RegisterValidation("customBirthday", func(v interface{}, param string) bool {
dateStr, ok := v.(string)
if !ok {
return false
}
_, err := time.Parse("2006-01-02", dateStr)
return err == nil
})
}
func main() {
user := User{
Username: "johndoe",
Email: "john@example.com",
Age: 25,
Password: "secure123",
Birthday: "1995-05-15",
Interests: []string{"编程", "音乐", "旅行"},
Address: Address{
City: "北京",
Country: "中国",
},
}
if ok, err := valid.Check(user); !ok {
fmt.Println("验证失败:", err)
return
}
fmt.Println("验证通过!")
}
总结
checker 库提供了一种简洁的方式来验证 Go 结构体数据:
- 通过结构体标签声明验证规则
- 支持常见的数据类型验证
- 可以自定义验证规则和错误消息
- 支持嵌套结构体和切片验证
这种方法使验证逻辑与业务代码分离,提高了代码的可读性和可维护性。对于更复杂的需求,也可以考虑其他验证库如 go-playground/validator 或 ozzo-validation。