go中validate包使用教程

前言

在go项目中,经常有校验数据合法性的需求,比如邮箱、年龄、车牌号、网址、字符串长度、金额、枚举范围等。一个好的校验包能帮我们少写很多ifelse,提高系统的可维护性。
validate包内置了丰富的校验语法,包括字符串、数字、邮箱等,当然如果我们有定制化的校验提示文案或者校验规则,validate也支持定制化校验。

安装

# 安装validate包
$ go get github.com/go-playground/validator/v10
# 项目中引入包
import "github.com/go-playground/validator/v10"

简单使用

校验语法:在字段tag上,也就是字段类型后面的`xxx`里内容,加上validate:“yyy”,其中yyy就是validate的校验语法;
校验方法:使用err := validate.Struct(u)进行校验,err是校验结果
结果输出:我们可以对err进行反射判断处理,可以获取字段名等信息,定制化输出校验结果
下面是一个简单示例:


import (
	"fmt"
	"github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	zhTrans "github.com/go-playground/validator/v10/translations/zh"
)

type User struct {
	Name  string
	Age   int    `validate:"required,gte=18,lte=55"`
	Email string `validate:"required,email"`
}

func ValidTestSimple() {
	u := &User{
		Name:  "tt",
		Age:   12,
		Email: "abcde@gmail",
	}

	validSimple := validator.New()
	err := validSimple.Struct(u)
	if err != nil {
		for _, e := range err.(validator.ValidationErrors) {
			fmt.Printf(e.String())
			fmt.Println()
		}
	} else {
		fmt.Println("validate success!")
	}
}
func main() {
	ValidTestSimple()
}

让我们看看输出

Key: 'User.Age' Error:Field validation for 'Age' failed on the 'gte' tag
Key: 'User.Email' Error:Field validation for 'Email' failed on the 'email' tag

看这个这个输出,validate已经生效,校验了age字段必须是18-55的数字范围,12不符合;email字段abcde@gmail不是一个合法的邮箱,是不是很简单,继续往下看。

错误处理

Validator对于错误的验证输入只返回InvalidValidationError,nil或ValidationErrors作为类型错误;因此,在您的代码中,您所需要做的就是检查返回的错误是否不是nil,如果不是,则检查错误是否为InvalidValidationError(如有必要,大多数情况下不是),将其类型转换为ValidationErrors类型,如下所示:

err := validate.Struct(mystruct)
validationErrors := err.(validator.ValidationErrors)

翻译器

一般来说,对于数据验证结果文案,在产品上有特殊要求,我们可以按照上面的错误处理,遍历validationErrors,判断字段类型,指定文案返回。
通常,如果对文案没有指定要求,我们可以使用下面的翻译器配合验证对象,输出中文容易理解的验证结果,而不是返回内置的英文验证结果。
翻译器包:github.com/go-playground/universal-translator@v0.18.1
配合validate使用示例:

package main

import (
	"fmt"
	"github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	zhTrans "github.com/go-playground/validator/v10/translations/zh"
)

type User struct {
	Name  string
	Age   int    `validate:"required,gte=18,lte=55"`
	Email string `validate:"required,email"`
}

func ValidTestSimple() {
	u := &User{
		Name:  "tt",
		Age:   12,
		Email: "abcde@gmail",
	}
	// 新建验证对象
	validSimple := validator.New()
	// 新建中文翻译器,类型为
	// type UniversalTranslator struct {
	// 	   translators map[string]Translator
	//     fallback    Translator
    // }
	trans := ut.New(zh.New())
	
	// 取其中的Translator
	zhTran, _ := trans.GetTranslator("zh")
	// 注册翻译器到验证对象上
	zhTrans.RegisterDefaultTranslations(validSimple, zhTran)
	// 开始验证
	err := validSimple.Struct(u)
	if err != nil {
		for _, e := range err.(validator.ValidationErrors) {
			// 输出翻译后的验证结果
			fmt.Printf(e.Translate(zhTran))
			fmt.Println()
			// 输出未翻译的验证结果
			fmt.Println(e.Error())
		}
	} else {
		fmt.Println("validate success!")
	}
}
func main() {
		ValidTestSimple()
}

未添加翻译器时:

Key: 'User.Age' Error:Field validation for 'Age' failed on the 'gte' tag
Key: 'User.Email' Error:Field validation for 'Email' failed on the 'email' tag

添加翻译器时校验结果:

Age必须大于或等于18
Email必须是一个有效的邮箱

Validator库介绍

官网文档

校验语法常用标记

标记作用示例
len长度validate:“len=12” ,只能用等于,不能用其他比较符号
gt大于validate:“gt=12”,只能用于数字类型
gte大于等于validate:“gte=0”,只能用于数字类型
lt小于validate:“lt=0”,只能用于数字类型
lte小于等于validate:“lte=12”,只能用于数字类型
min最小值validate:“min=12”,只能用于数字类型
max最大值validate:“max=12”,只能用于数字类型
oneof其中之一validate:“oneof=cc vv aa”
unique是否唯一,通常用于数组和切片validate:“unique”
numeric字符串是否只包含基础的数值validate:“numeric”
json字符串是否为有效的jsonvalidate:“json”
contains字符串是否包含子字符串的值validate:“contains=aa”
url字符串是否为有效的urlvalidate:“url”
ip字符串是否为有效的ipvalidate:“ip”

自定义校验

需求【校验车身颜色】

需求描述
车身颜色枚举为【黑色、白色、绿色、红色、粉色】,如果输入的车身颜色不在这个范围中,输出校验结果:车身颜色取值必须是黑色、白色、绿色、红色、粉色;
思路

  1. 初始化validate包
  2. 自定义车身颜色枚举
  3. 自定义车身颜色校验方法和输出格式
  4. 捕捉validate校验的错误,判断是否为枚举
  5. 填充输出返回
    代码
    1.初始化validate
package customvalid

import (
	"bytes"
	"errors"
	"fmt"
	locales_zh "github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	translations_zh "github.com/go-playground/validator/v10/translations/zh"
	"validate/customvalid/enum"
)

const (
	ValidEnum                = "valid_enum"
	ValidEnumComment         = "%s取值范围只能是%s"
	ValidEnumCommentNotFound = "校验失败,%s没有对应的枚举"
)

var validateObj *validator.Validate
var globalZhTranslator ut.Translator

func InitValid() {
	registerZhTransactions()
	registerCustomValid()
}

// 注册中文翻译器
func registerZhTransactions() {
	universalTranslator := ut.New(locales_zh.New(), locales_zh.New())
	zhTranslator, ok := universalTranslator.GetTranslator("zh")
	if !ok {
		panic("无可用翻译器")
	}
	validateObj = validator.New()
	globalZhTranslator = zhTranslator
	translations_zh.RegisterDefaultTranslations(validateObj, zhTranslator)
}

// 注册校验器
func registerCustomValid() {
	validateObj = validator.New()
	validateObj.RegisterValidation(ValidEnum, ValidEnumFc)
}

func ValidateStruct(s interface{}) error {
	buffer := bytes.NewBufferString("")
	err := validateObj.Struct(s)
	if err != nil {
		for _, errField := range err.(validator.ValidationErrors) {
			switch errField.Tag() {
			case ValidEnum:
				enumType := enum.BuildEnum(errField.Param())
				if enumType == nil {
					buffer.WriteString(fmt.Sprintf(ValidEnumCommentNotFound, errField.StructField()))
				} else {
					buffer.WriteString(fmt.Sprintf(ValidEnumComment, errField.StructField(), enumType.AllEnumComments()))
				}
			}
		}
	}
	if buffer.String() != "" {
		return errors.New(buffer.String())
	}
	return nil
}

// 校验在固定枚举中
func ValidEnumFc(fl validator.FieldLevel) bool {
	fieldName := fl.Param()
	enumType := enum.BuildEnum(fieldName)
	return enumType != nil && enumType.ValidEnumValue((int32)(fl.Field().Int()))
}

demo仓库:https://gitee.com/fengyurong/validate,敬请star!!

  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vuevalidate()方法通常用于表单验证。下面是一个使用案例: 1. 在你的Vue组件,定义一个名为valid的data属性,用于存储表单验证的状态: ``` data() { return { valid: false, form: { // 表单数据 }, rules: { // 表单验证规则 } } } ``` 2. 在表单绑定v-model指令,将表单数据与组件实例的form属性进行绑定: ``` <el-form :model="form"> <el-form-item label="用户名" prop="username"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="密码" prop="password"> <el-input type="password" v-model="form.password"></el-input> </el-form-item> <!-- 其他表单项 --> <el-button type="primary" @click="submitForm">提交</el-button> </el-form> ``` 3. 在submitForm方法,调用validate()方法进行表单验证。如果验证通过,将valid的值设置为true,否则为false: ``` methods: { submitForm() { this.$refs.form.validate((valid) => { if (valid) { this.valid = true // 提交表单数据 } else { this.valid = false return false } }) } } ``` 4. 在表单项定义验证规则,例如: ``` rules: { username: [ { required: true, message: '请输入用户名', trigger: 'blur' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' } ] } ``` 这样,在提交表单时,validate()方法会对表单数据按照验证规则进行验证,如果有验证失败的情况,会返回false并提示错误信息。如果所有验证规则都通过,返回true并提交表单数据。通过valid属性来判断表单是否验证通过。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值