golang基于标签快速验证结构体的插件库govalid的使用

Golang基于标签快速验证结构体的插件库govalid的使用

基本示例

Govalid是一个用于验证结构体的Golang库,它通过结构体标签来定义验证规则。下面是一个基本使用示例:

package main

import (
	"errors"
	"fmt"
	"log"
	"strings"
	"unicode/utf8"

	"github.com/twharmon/govalid"
)

type Post struct {
	// ID没有约束
	ID int

	// Title是必填字段,至少3个字符,最多20个字符
	Title string `valid:"req|min:3|max:20"`

	// Body不是必填字段,最多10000个字符,且必须满足"fun"规则(下面定义的自定义规则)
	Body string `valid:"max:10000|fun"`
}

func main() {
	// 添加自定义字符串规则"fun",可以用于任何结构体中的字符串字段
	govalid.Rule("fun", func(v any) error {
		switch tv := v.(type) {
		case string:
			if float64(strings.Count(tv, "!"))/float64(utf8.RuneCountInString(tv)) > 0.001 {
				return nil
			}
			// 使用govalid.NewValidationError返回验证错误
			return govalid.NewValidationError("必须包含更多感叹号")
		default:
			// 返回非验证(内部)错误
			return errors.New("fun约束只能应用于字符串")
		}
	})
	fmt.Println(govalid.Validate(&Post{
		ID:    5,
		Title: "Hi",
		Body:  "Hello world!",
	}))
}

错误处理

当调用govalid.Validate验证结构体时,如果验证规则不满足会返回错误。这个错误可能是验证特定的错误(实现了govalid.ValidationError接口),也可能是处理验证时出现的其他错误。

if err := govalid.Validate(value); err != nil {
	verr, ok := err.(govalid.ValidationError)
	if ok {
		fmt.Println("验证错误", err)
	} else {
		fmt.Println("其他错误", err)
	}
}

Dive规则用法

dive规则用于对指针、切片、数组和结构体中的元素应用验证规则。当遇到dive规则时,它会"深入"到集合的元素或指针指向的值,并对每个元素或解引用后的值应用剩余的规则。

注意事项

  • 指针dive规则会解引用指针并对指向的值应用剩余规则
  • 切片/数组dive规则会遍历切片或数组中的每个元素并应用剩余规则
  • 结构体dive规则会根据结构体自身的字段标签验证结构体

示例

指针

type Example struct {
    Field *string `valid:"req|dive|min:3"`
}

在这个例子中,Field必须是一个非nil的字符串指针,并且字符串长度至少为3个字符。

切片/数组

type Example struct {
    Field []string `valid:"req|dive|min:3"`
}

在这个例子中,Field必须是一个非nil的字符串切片,并且切片中的每个字符串长度至少为3个字符。

结构体

type Inner struct {
    Name string `valid:"req"`
}

type Outer struct {
    InnerStruct Inner `valid:"dive"`
}

在这个例子中,InnerStruct字段将根据Inner结构体中定义的验证标签进行验证。


更多关于golang基于标签快速验证结构体的插件库govalid的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang基于标签快速验证结构体的插件库govalid的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用govalid进行Golang结构体验证

govalid是一个基于标签的Golang结构体验证库,它允许开发者通过结构体标签快速定义验证规则,简化了数据验证的过程。下面我将详细介绍govalid的使用方法。

安装govalid

首先需要安装govalid库:

go get github.com/gopherd/govalid

基本用法

1. 定义带有验证标签的结构体

type User struct {
    Name     string `valid:"required,minlen=4,maxlen=20"`
    Age      int    `valid:"required,min=18,max=120"`
    Email    string `valid:"required,email"`
    Password string `valid:"required,minlen=8"`
    Phone    string `valid:"phone"`
}

2. 验证结构体

package main

import (
    "fmt"
    "github.com/gopherd/govalid"
)

func main() {
    user := User{
        Name:     "John",
        Age:      17,
        Email:    "invalid-email",
        Password: "short",
    }

    err := govalid.Validate(user)
    if err != nil {
        if verr, ok := err.(*govalid.ValidationError); ok {
            for field, msg := range verr.Fields {
                fmt.Printf("%s: %s\n", field, msg)
            }
        } else {
            fmt.Println("Validation error:", err)
        }
    } else {
        fmt.Println("Validation passed!")
    }
}

常用验证标签

govalid支持多种验证规则:

  1. required - 字段必须存在且非零值
  2. minlen=n - 字符串最小长度
  3. maxlen=n - 字符串最大长度
  4. min=n - 数字最小值
  5. max=n - 数字最大值
  6. email - 必须是有效的电子邮件格式
  7. phone - 必须是有效的电话号码格式
  8. regex=pattern - 必须匹配正则表达式
  9. in=value1,value2,… - 必须在指定值列表中
  10. notin=value1,value2,… - 不能在指定值列表中

自定义验证器

1. 定义自定义验证函数

func isAdminUser(value interface{}) error {
    s, ok := value.(string)
    if !ok {
        return fmt.Errorf("expected string type")
    }
    if s != "admin" {
        return fmt.Errorf("must be admin user")
    }
    return nil
}

2. 注册自定义验证器

func init() {
    govalid.RegisterValidator("admin", isAdminUser)
}

3. 使用自定义验证器

type Admin struct {
    Username string `valid:"required,admin"`
}

嵌套结构体验证

govalid支持嵌套结构体的验证:

type Address struct {
    Street  string `valid:"required"`
    City    string `valid:"required"`
    Country string `valid:"required"`
}

type Person struct {
    Name    string  `valid:"required"`
    Age     int     `valid:"required,min=18"`
    Address Address `valid:"required"`
}

切片和数组验证

type Team struct {
    Members []string `valid:"required,minlen=1,maxlen=10,unique"`
    Scores  []int    `valid:"required,min=0,max=100"`
}

条件验证

可以使用requiredIfrequiredUnless实现条件验证:

type Order struct {
    PaymentMethod string `valid:"required,in=cash,credit"`
    CreditCard    string `valid:"requiredIf=PaymentMethod credit"`
    CashReceipt   bool   `valid:"requiredUnless=PaymentMethod credit"`
}

性能优化

对于频繁验证的场景,可以预编译验证规则:

type Product struct {
    ID    string `valid:"required,uuid"`
    Name  string `valid:"required"`
    Price float64 `valid:"required,min=0"`
}

func main() {
    validator, err := govalid.Compile(Product{})
    if err != nil {
        panic(err)
    }
    
    // 然后可以重复使用validator
    product := Product{ID: "123", Name: "Laptop", Price: -1}
    err = validator.Validate(product)
    // 处理错误...
}

错误消息自定义

可以通过实现govalid.ErrorTransformer接口来自定义错误消息:

type customErrorTransformer struct{}

func (t *customErrorTransformer) Transform(err error) error {
    if verr, ok := err.(*govalid.ValidationError); ok {
        // 自定义错误消息格式
        var msgs []string
        for field, msg := range verr.Fields {
            msgs = append(msgs, fmt.Sprintf("%s: %s", field, msg))
        }
        return fmt.Errorf("验证失败: %s", strings.Join(msgs, "; "))
    }
    return err
}

func main() {
    govalid.SetErrorTransformer(&customErrorTransformer{})
    // 现在所有验证错误都会使用自定义格式
}

govalid是一个轻量级但功能强大的验证库,通过结构体标签可以快速实现复杂的数据验证逻辑,非常适合在Golang项目中使用。

回到顶部