【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

相关推荐
workflower10 分钟前
活动图描述场景
开发语言·软件工程·需求分析·软件需求·敏捷流程
梦想的初衷~12 分钟前
基于现代R语言【Tidyverse、Tidymodel】的机器学习方法
开发语言·机器学习·r语言
香蕉可乐荷包蛋15 分钟前
Python学习之路(十三)-常用函数的使用,及优化
开发语言·python·学习
惜.己23 分钟前
使用python的读取xml文件,简单的处理成元组数组
xml·开发语言·python·测试工具
来自旧金山的勇士39 分钟前
WSL->Ubunut安装Redis
后端
大葱白菜41 分钟前
Java Set 集合详解:从基础语法到实战应用,彻底掌握去重与唯一性集合
java·后端
大葱白菜42 分钟前
Java Map 集合详解:从基础语法到实战应用,彻底掌握键值对数据结构
java·后端
apihz1 小时前
域名WHOIS信息查询免费API使用指南
android·开发语言·数据库·网络协议·tcp/ip
小猪乔治爱打球1 小时前
[Golang修仙之路] 算法专题:回溯(递归)
后端·面试
昵称为空C1 小时前
SpringBoot数据存储时区选择,符合国际化和特定时区方案
spring boot·后端