【Golang】validator库的使用

Go 复制代码
package main

import (
	"fmt"

	"github.com/go-playground/validator"
)

// MyStruct .. validate:"is-awesome"是一个结构体标签,它告诉验证器使用名为is-awesome的验证规则来验证String字段。
type MyStruct struct {
	String string `validate:"is-awesome"`
}

// use a single instance of Validate, it caches struct info
var validate *validator.Validate

func main() {

	validate = validator.New()
	//注册一个自定义验证函数ValidateMyVal,它将被用来验证标签为is-awesome的字段。
	validate.RegisterValidation("is-awesome", ValidateMyVal)

	s := MyStruct{String: "awesome"}

	err := validate.Struct(s)
	if err != nil {
		fmt.Printf("Err(s):%+v\n", err)
	}

	s.String = "not awesome"
	err = validate.Struct(s)
	if err != nil {
		fmt.Printf("Err(s):\n%+v\n", err)
	}
}

// ValidateMyVal implements validator.Func
func ValidateMyVal(fl validator.FieldLevel) bool {
	return fl.Field().String() == "awesome"
}

custom-validation 结果

复制代码
Err(s):
Key: 'MyStruct.String' Error:Field validation for 'String' failed on the 'is-awesome' tag

示例代码2

custom

Go 复制代码
package main

import (
	"database/sql"
	"database/sql/driver"
	"fmt"
	"reflect"

	"github.com/go-playground/validator/v10"
)

// DbBackedUser 用户结构体,由数据库支持
type DbBackedUser struct {
	Name sql.NullString `validate:"required"` // 可以为NULL的字符串,验证规则为必填
	Age  sql.NullInt64  `validate:"required"` // 可以为NULL的整数,验证规则为必填
}

// 使用单一实例的验证器,它缓存结构体信息
var validate *validator.Validate

func main() {
	// 创建一个新的验证器实例
	validate = validator.New()

	// 注册所有sql.Null*类型,使用自定义的ValidateValuer函数
	validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})

	// 构建对象进行验证
	// Name字段为空字符串但Valid为true,表示非NULL;Age字段为0且Valid为false,表示NULL
	x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}}

	// 对x进行结构体验证
	err := validate.Struct(x)

	// 如果验证失败,打印错误信息
	if err != nil {
		fmt.Printf("Err(s):\n%+v\n", err)
	}
}

// ValidateValuer实现了validator.CustomTypeFunc接口
func ValidateValuer(field reflect.Value) interface{} {
	// 如果field实现了driver.Valuer接口
	if valuer, ok := field.Interface().(driver.Valuer); ok {
		// 尝试获取valuer的值
		val, err := valuer.Value()
		if err == nil {
			return val // 如果没有错误,返回值
		}
		// 如果有错误,可以根据需要处理
	}
	return nil // 如果没有实现Valuer接口或有错误,返回nil
}
Go 复制代码
// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) Struct(s interface{}) error {
	return v.StructCtx(context.Background(), s)
}

// StructCtx validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified
// and also allows passing of context.Context for contextual validation information.
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructCtx(ctx context.Context, s interface{}) (err error) {

	val := reflect.ValueOf(s)
	top := val

	if val.Kind() == reflect.Ptr && !val.IsNil() {
		val = val.Elem()
	}

	if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
		return &InvalidValidationError{Type: reflect.TypeOf(s)}
	}

	// good to validate
	vd := v.pool.Get().(*validate)
	vd.top = top
	vd.isPartial = false
	// vd.hasExcludes = false // only need to reset in StructPartial and StructExcept

	vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)

	if len(vd.errs) > 0 {
		err = vd.errs
		vd.errs = nil
	}

	v.pool.Put(vd)

	return
}

参考validator/_examples at master · go-playground/validator · GitHub

相关推荐
名字还没想好☜6 小时前
Java 线上内存泄漏排查实战:jmap 导堆、MAT 找 GC Roots 与四类常见泄漏
java·开发语言·jvm·内存泄漏
码匠许师傅6 小时前
【C++ 面试真题】聊聊 C++ 的多继承与虚继承
开发语言·c++·面试
我不是疯子是傻子7 小时前
Qt CAN通信周期发送抖动?实测定时器精度校准与时间戳补偿方案
开发语言·数据库·qt
IT_陈寒7 小时前
Vue的双向绑定把我坑惨了,原来这个场景不能用
前端·人工智能·后端
IT爱学堂7 小时前
尚硅谷 - 2025年3月Java+AI大模型应用开发
java·开发语言·人工智能
有点。7 小时前
C++认识数
开发语言·c++
31535669138 小时前
DeepSeek Harness 发布后,我没急着跑 Demo,先把 `.agents/` 翻了一遍
前端·后端·github
Nturmoils8 小时前
不在公司,也能连回办公电脑:用 Natapp 打通 Windows 远程桌面
后端
LEE8 小时前
AI Agent 都在疯狂加功能,它说:我全砍了
前端·后端
W_326009 小时前
Python文件进阶:一维数据与 CSV 文件读写
开发语言·python