first commit
This commit is contained in:
78
internal/pkg/validation/validation.go
Normal file
78
internal/pkg/validation/validation.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// 使用预编译的全局正则表达式,避免重复创建和编译.
|
||||
var (
|
||||
lengthRegex = regexp.MustCompile(`^.{3,20}$`) // 长度在 3 到 20 个字符之间
|
||||
validRegex = regexp.MustCompile(`^[A-Za-z0-9_]+$`) // 仅包含字母、数字和下划线
|
||||
letterRegex = regexp.MustCompile(`[A-Za-z]`) // 至少包含一个字母
|
||||
numberRegex = regexp.MustCompile(`\d`) // 至少包含一个数字
|
||||
emailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`) // 邮箱格式
|
||||
phoneRegex = regexp.MustCompile(`^1[3-9]\d{9}$`) // 中国手机号
|
||||
)
|
||||
|
||||
// IsValidUsername 校验用户名是否合法.
|
||||
func IsValidUsername(username string) bool {
|
||||
// 校验长度
|
||||
if !lengthRegex.MatchString(username) {
|
||||
return false
|
||||
}
|
||||
// 校验字符合法性
|
||||
if !validRegex.MatchString(username) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsValidPassword 判断密码是否符合复杂度要求.
|
||||
func IsValidPassword(password string) error {
|
||||
switch {
|
||||
// 检查新密码是否为空
|
||||
case password == "":
|
||||
return errors.New("password cannot be empty")
|
||||
// 检查新密码的长度要求
|
||||
case len(password) < 6:
|
||||
return errors.New("password must be at least 6 characters long")
|
||||
// 使用正则表达式检查是否至少包含一个字母
|
||||
case !letterRegex.MatchString(password):
|
||||
return errors.New("password must contain at least one letter")
|
||||
// 使用正则表达式检查是否至少包含一个数字
|
||||
case !numberRegex.MatchString(password):
|
||||
return errors.New("password must contain at least one number")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValidEmail 判断电子邮件是否合法.
|
||||
func IsValidEmail(email string) error {
|
||||
// 检查电子邮件地址格式
|
||||
if email == "" {
|
||||
return errors.New("email cannot be empty")
|
||||
}
|
||||
|
||||
// 使用正则表达式校验电子邮件格式
|
||||
if !emailRegex.MatchString(email) {
|
||||
return errors.New("invalid email format")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValidPhone 判断手机号码是否合法.
|
||||
func IsValidPhone(phone string) error {
|
||||
// 检查手机号码格式
|
||||
if phone == "" {
|
||||
return errors.New("phone cannot be empty")
|
||||
}
|
||||
|
||||
// 使用正则表达式校验手机号码格式(假设是中国手机号,11位数字)
|
||||
if !phoneRegex.MatchString(phone) {
|
||||
return errors.New("invalid phone format")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
86
internal/pkg/validation/validator.go
Normal file
86
internal/pkg/validation/validator.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
// 初始化一个验证器实例
|
||||
var validate = validator.New()
|
||||
|
||||
// 自定义验证规则:requiredint
|
||||
func init() {
|
||||
validate.RegisterValidation("telephone", func(fl validator.FieldLevel) bool {
|
||||
if err := IsValidPhone(fl.Field().String()); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
validate.RegisterValidation("dateonly", func(fl validator.FieldLevel) bool {
|
||||
_, err := time.ParseInLocation("2006-01-02", fl.Field().String(), time.Local)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func ValidateForm(s any) error {
|
||||
// 验证结构体数据
|
||||
if err := validate.Struct(s); err != nil {
|
||||
if _, ok := err.(*validator.InvalidValidationError); ok {
|
||||
return errors.New("验证器配置错误")
|
||||
}
|
||||
|
||||
// 获取结构体的反射类型
|
||||
t := reflect.TypeOf(s)
|
||||
|
||||
errorMessages := make([]string, 0)
|
||||
for _, err := range err.(validator.ValidationErrors) {
|
||||
// 获取字段名
|
||||
fieldName := err.Field()
|
||||
// 获取标签名
|
||||
tag := err.Tag()
|
||||
// 获取验证失败的字段值
|
||||
// value := err.Value()
|
||||
|
||||
// 通过反射获取字段
|
||||
field, found := t.Elem().FieldByName(fieldName)
|
||||
errorMsg := fmt.Sprintf("[%s] 验证失败: %s", fieldName, translate(tag))
|
||||
if found {
|
||||
commentTag := field.Tag.Get("comment")
|
||||
errorMsg = fmt.Sprintf("[%s] 验证失败: %s", commentTag, translate(tag))
|
||||
}
|
||||
|
||||
errorMessages = append(errorMessages, errorMsg)
|
||||
}
|
||||
return errors.New(strings.Join(errorMessages, "; "))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func translate(s string) string {
|
||||
switch s {
|
||||
case "required":
|
||||
return "不能为空"
|
||||
case "min":
|
||||
return "不能小于"
|
||||
case "max":
|
||||
return "不能大于"
|
||||
case "email":
|
||||
return "不是有效的邮箱地址"
|
||||
case "telephone":
|
||||
return "不是有效的手机号"
|
||||
case "datetime":
|
||||
return "不是有效的日期时间"
|
||||
case "dateonly":
|
||||
return "不是有效的日期"
|
||||
}
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user