golang轻量级结构体验证插件库gody的使用

golang轻量级结构体验证插件库gody的使用

安装

go get github.com/guiferpa/gody/v2

使用示例

下面是一个完整的HTTP服务示例,展示如何使用gody进行结构体验证:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"

    gody "github.com/guiferpa/gody/v2"
    "github.com/guiferpa/gody/v2/rule"
)

// 定义请求体结构
type RequestBody struct {
    Name string `json:"name" validate:"not_empty"`  // 验证name字段不能为空
    Age  int    `json:"age" validate:"min=21"`     // 验证age字段最小值为21
}

// HTTP处理函数
func HTTPHandler(v *gody.Validator) http.HandlerFunc {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        var body RequestBody
        if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
            http.Error(w, "Invalid request body", http.StatusBadRequest)
            return
        }
        defer r.Body.Close()

        // 验证请求体
        if isValidated, err := v.Validate(body); err != nil {
            http.Error(w, fmt.Sprintf("Validation error: %v", err), http.StatusBadRequest)
            return
        } else if !isValidated {
            http.Error(w, "Validation failed", http.StatusBadRequest)
            return
        }

        // 验证通过的处理逻辑
        fmt.Fprintf(w, "Validation passed! Name: %s, Age: %d", body.Name, body.Age)
    })
}

func main() {
    // 创建验证器实例
    validator := gody.NewValidator()

    // 添加验证规则
    validator.AddRules(rule.NotEmpty, rule.Min)

    // 启动HTTP服务
    port := ":3000"
    fmt.Printf("Server started on port %s\n", port)
    http.ListenAndServe(port, HTTPHandler(validator))
}

其他验证方式

gody提供了多种验证函数:

  1. RawValidate - 无需预定义规则的验证函数,需要传入结构体、标签名和规则列表
gody.RawValidate(interface{}, string, []gody.Rule) (bool, error)
  1. Validate - 无需预定义规则的验证函数,需要传入结构体和规则列表
gody.Validate(interface{}, []gody.Rule) (bool, error)
  1. RawDefaultValidate - 使用内置规则的验证函数,需要传入结构体、标签名和可选的自定义规则
gody.RawDefaultValidate(interface{}, string, []gody.Rule) (bool, error)
  1. DefaultValidate - 使用内置规则的验证函数,需要传入结构体和可选的自定义规则
gody.DefaultValidate(interface{}, []gody.Rule) (bool, error)

动态枚举验证(避免重复)

可以通过动态参数避免在结构体标签中重复枚举值:

const (
    StatusCreated = "__CREATED__"
    StatusPending = "__PENDING__"
    StatusDoing   = "__DOING__"
    StatusDone    = "__DONE__"
)

type Task struct {
    Name   string `json:"name"`
    Status string `json:"status" validate:"enum={status}"`  // 使用动态参数
}

validator := gody.NewValidator()
validator.AddRuleParameters(map[string]string{
    "status": fmt.Sprintf("%s,%s,%s,%s", StatusCreated, StatusPending, StatusDoing, StatusDone),
})
validator.AddRules(rule.Enum)

// 现在可以验证Task结构体而无需在标签中重复枚举值

贡献政策

  1. 目前唯一的政策是不要直接创建Pull Request,在实现之前需要通过issue进行讨论。

更多关于golang轻量级结构体验证插件库gody的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang轻量级结构体验证插件库gody的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go轻量级结构体验证库 - gody 使用指南

gody 是一个轻量级的 Go 结构体验证库,它简单易用且不依赖反射,适合需要快速验证结构体数据的场景。

安装

go get github.com/guiferpa/gody

基本使用

1. 简单验证

package main

import (
	"fmt"
	"github.com/guiferpa/gody"
)

type User struct {
	Name  string `json:"name" validate:"not_empty"`
	Email string `json:"email" validate:"not_empty,email"`
	Age   int    `json:"age" validate:"min=18"`
}

func main() {
	user := User{
		Name:  "John Doe",
		Email: "john@example.com",
		Age:   25,
	}

	// 注册默认验证规则
	gody.RegisterDefaultRules()

	// 验证结构体
	if err := gody.Validate(user); err != nil {
		fmt.Println("Validation error:", err)
	} else {
		fmt.Println("Validation passed!")
	}
}

2. 内置验证规则

gody 提供了一些内置验证规则:

  • not_empty - 字段不能为空
  • email - 必须是有效的电子邮件格式
  • min - 数字最小值 (如 min=18)
  • max - 数字最大值 (如 max=100)
  • len - 字符串长度 (如 len=10)
  • uuid - 必须是有效的UUID
  • regexp - 正则表达式匹配 (如 regexp=^[a-zA-Z]+$)

3. 自定义验证规则

package main

import (
	"fmt"
	"github.com/guiferpa/gody"
	"strings"
)

type Product struct {
	Code  string `json:"code" validate:"not_empty,starts_with_P"`
	Price int    `json:"price" validate:"min=1"`
}

// 自定义验证函数
func startsWithP(rule string, value interface{}) error {
	s, ok := value.(string)
	if !ok {
		return fmt.Errorf("starts_with_P: value must be a string")
	}
	
	if !strings.HasPrefix(s, "P") {
		return fmt.Errorf("starts_with_P: value must start with 'P'")
	}
	
	return nil
}

func main() {
	product := Product{
		Code:  "P12345",
		Price: 100,
	}

	// 注册默认规则
	gody.RegisterDefaultRules()
	
	// 注册自定义规则
	gody.RegisterRule("starts_with_P", startsWithP)

	if err := gody.Validate(product); err != nil {
		fmt.Println("Validation error:", err)
	} else {
		fmt.Println("Validation passed!")
	}
}

4. 验证嵌套结构体

package main

import (
	"fmt"
	"github.com/guiferpa/gody"
)

type Address struct {
	Street string `json:"street" validate:"not_empty"`
	City   string `json:"city" validate:"not_empty"`
}

type Customer struct {
	Name    string  `json:"name" validate:"not_empty"`
	Address Address `json:"address" validate:"struct"`
}

func main() {
	customer := Customer{
		Name: "Jane Smith",
		Address: Address{
			Street: "123 Main St",
			City:   "",
		},
	}

	gody.RegisterDefaultRules()

	if err := gody.Validate(customer); err != nil {
		fmt.Println("Validation error:", err)
		// 输出: Validation error: address.city: cannot be empty
	}
}

5. 切片验证

package main

import (
	"fmt"
	"github.com/guiferpa/gody"
)

type Item struct {
	ID    string `json:"id" validate:"not_empty,uuid"`
	Name  string `json:"name" validate:"not_empty"`
	Count int    `json:"count" validate:"min=1"`
}

type Order struct {
	Items []Item `json:"items" validate:"not_empty"`
}

func main() {
	order := Order{
		Items: []Item{
			{
				ID:    "550e8400-e29b-41d4-a716-446655440000",
				Name:  "Laptop",
				Count: 1,
			},
			{
				ID:    "",
				Name:  "Mouse",
				Count: 0,
			},
		},
	}

	gody.RegisterDefaultRules()

	if err := gody.Validate(order); err != nil {
		fmt.Println("Validation error:", err)
		// 输出: Validation error: items[1].id: cannot be empty; items[1].count: must be greater than or equal to 1
	}
}

性能考虑

gody 相比其他验证库(如 go-playground/validator)有以下特点:

  1. 不使用反射,性能更好
  2. 验证规则更简单,功能相对较少
  3. 适合简单到中等复杂度的验证需求

总结

gody 是一个轻量级的验证库,适合那些:

  • 需要简单快速验证的场景
  • 对性能有要求的应用
  • 不需要复杂验证逻辑的项目

对于更复杂的验证需求,可能需要考虑其他功能更全面的验证库。但如果你需要一个小巧、快速的验证工具,gody 是一个不错的选择。

回到顶部