每日一库golang validator常规参数校验及自定义规则校验,自定义返回中文错误信息
1.validator简介
validator是一个开源的验证器包,可以快速校验输入信息是否符合自定规则。源码地址: https://github.com/go-playground/validator
本地开发安装库:
go get github.com/go-playground/validator
示例用户名与密码校验
package main import ( "fmt" "github.com/go-playground/validator/v10" "reflect" "regexp" ) func main() { u := User{ Username: "IamJames", Password: "1234567A$888", } validate := validator.New() _ = validate.RegisterValidation("minLen", minLen) _ = validate.RegisterValidation("verifyPwd", verifyPwd) err := validate.Struct(u) if err != nil { errInfo := processErr(u, err) fmt.Printf("error: %v\n", err) fmt.Printf("errorInfo: %v\n", errInfo) return } fmt.Println("validate pass...") } type User struct { Username string `json:"username,omitempty" validate:"required,minLen" field_error_info:"用户名最少6个字符"` Password string `json:"password,omitempty" validate:"required,verifyPwd" field_error_info:"密码应包含数字、大/小写字母、特殊字符中的3种, 且至少8个字符"` Email string `json:"email" validate:"required,email"` // 限于email格式 Phone string `json:"phone" validate:"omitempty,numeric"` // 限于数字型 Hobby []string `json:"hobby" validate:"omitempty"` // 空时忽略 Age int `json:"age" validate:"omitempty,gt=18,lt=100"` // 限制大小 Gender string `json:"gender" validate:"omitempty,oneof=male female"` // 限于男女 Nickname string `json:"nickname" validate:"required,min=4,max=20"` // 必填字段,限制长度 } func minLen(f validator.FieldLevel) bool { val := f.Field().String() if len(val) < 6 { return false } return true } func verifyPwd(f validator.FieldLevel) bool { val := f.Field().String() if len(val) < 8 || len(val) > 20 { // length需要通过验证 fmt.Println("pwd length error") return false } pwdPattern := `^[0-9a-zA-Z!@#$%^&*~-_+]{8,20}$` reg, err := regexp.Compile(pwdPattern) // filter exclude chars if err != nil { return false } match := reg.MatchString(val) if !match { fmt.Println("not match error.") return false } var cnt int = 0 // 满足3中以上即可通过验证 patternList := []string{ // 数字、大小写字母、特殊字符 `[0-9]+`, `[a-z]+`, `[A-Z]+`, `[!@#$%^&*~-_+]+`, } for _, pattern := range patternList { match, _ = regexp.MatchString(pattern, val) if match { cnt++ } } if cnt < 3 { fmt.Println("pwd should include at least 3 types.") return false } return true } func processErr(u interface{},err error) string { if err == nil { //如果为nil 说明校验通过 return "" } invalid, ok := err.(*validator.InvalidValidationError) //如果是输入参数无效,则直接返回输入参数错误 if ok { return "输入参数错误:" + invalid.Error() } validationErrs := err.(validator.ValidationErrors) //断言是ValidationErrors for _, validationErr := range validationErrs { fieldName := validationErr.Field() //获取是哪个字段不符合格式 field, ok := reflect.TypeOf(u).FieldByName(fieldName) //通过反射获取filed if ok { errorInfo := field.Tag.Get("field_error_info") //获取field对应的reg_error_info tag值 return fieldName + ": " + errorInfo //返回错误 }else { return "缺失field_error_info" } } return "" }
返回信息
error: Key: 'User.Password' Error:Field validation for 'Password' failed on the 'verifyPwd' tag errorInfo: Password: 密码应包含数字、大/小写字母、特殊字符中的3种, 且至少8个字符