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: 确保字符串是有效的ISBN
  • lte: 确保值小于或等于指定数字
  • luhn: 确保字符串是有效的LUHN号码
  • mac: 确保字符串是有效的MAC地址
  • max-len: 确保给定值(字符串、切片或映射)的长度最多为n
  • min-len: 确保给定值(字符串、切片或映射)的长度至少为n
  • required: 确保提供了值
  • regexp: 确保字符串匹配模式
  • time: 确保字符串匹配提供的时间布局
  • url: 确保字符串是有效的URL

提供的标准化器

  • lower: 将字符串转换为小写
  • title: 将字符串转换为标题大小写
  • trim-left: 从字符串左侧修剪空白
  • trim-right: 从字符串右侧修剪空白
  • trim: 从字符串两侧修剪空白
  • upper: 将字符串转换为大写
  • html-escape: 转义字符串中的特殊字符以用于HTML
  • html-unescape: 取消转义字符串中的特殊字符以用于HTML
  • url-escape: 转义字符串中的特殊字符以用于URL
  • url-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

1 回复

更多关于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 支持多种验证规则:

  1. 必填验证

    • required - 字段不能为零值
  2. 字符串验证

    • min=5 - 最小长度5
    • max=20 - 最大长度20
    • len=10 - 长度必须为10
    • alpha - 只包含字母
    • alphanum - 只包含字母和数字
    • numeric - 必须是数字
    • email - 必须是邮箱格式
    • ip - 必须是IP地址
    • url - 必须是URL
  3. 数值验证

    • min=18 - 最小值18
    • max=100 - 最大值100
    • range=18-100 - 范围18-100
  4. 自定义正则

    • 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 结构体数据:

  1. 通过结构体标签声明验证规则
  2. 支持常见的数据类型验证
  3. 可以自定义验证规则和错误消息
  4. 支持嵌套结构体和切片验证

这种方法使验证逻辑与业务代码分离,提高了代码的可读性和可维护性。对于更复杂的需求,也可以考虑其他验证库如 go-playground/validator 或 ozzo-validation。

回到顶部