
在Go语言中,反射(reflect)和结构体标签(struct tag)是两个强大的特性,结合它们可以实现灵活的自动字段验证机制。这种机制常用于Web请求参数校验、配置检查等场景,无需重复编写大量if-else判断。
通过为结构体字段添加自定义tag,可以声明该字段的验证要求。例如:
type User struct {
Name string `validate:"required,min=2,max=20"`
Email string `validate:"required,email"`
Age int `validate:"min=0,max=150"`
}
这里的
validate
使用
reflect
立即学习“go语言免费学习笔记(深入)”;
func Validate(v interface{}) error {
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
if rv.Kind() != reflect.Struct {
return fmt.Errorf("expected struct, got %s", rv.Kind())
}
rt := rv.Type()
for i := 0; i < rv.NumField(); i++ {
field := rv.Field(i)
structField := rt.Field(i)
tag := structField.Tag.Get("validate")
if tag == "" || tag == "-" {
continue
}
if err := validateField(field, tag); err != nil {
return fmt.Errorf("%s: %v", structField.Name, err)
}
}
return nil
}
这段代码首先解引用指针类型,确保操作的是结构体本身。然后逐个读取字段的
validate
validateField
validateField
func validateField(field reflect.Value, tag string) error {
val := field.Interface()
strVal := ""
isString := false
if field.Kind() == reflect.String {
strVal = field.String()
isString = true
}
rules := strings.Split(tag, ",")
for _, rule := range rules {
switch {
case rule == "required":
if isZero(field) {
return errors.New("is required")
}
case strings.HasPrefix(rule, "min="):
min, _ := strconv.Atoi(strings.TrimPrefix(rule, "min="))
if isString && len(strVal) < min {
return fmt.Errorf("length must be >= %d", min)
} else if field.Kind() == reflect.Int {
if field.Int() < int64(min) {
return fmt.Errorf("must be >= %d", min)
}
}
case strings.HasPrefix(rule, "max="):
max, _ := strconv.Atoi(strings.TrimPrefix(rule, "max="))
if isString && len(strVal) > max {
return fmt.Errorf("length must be <= %d", max)
} else if field.Kind() == reflect.Int {
if field.Int() > int64(max) {
return fmt.Errorf("must be <= %d", max)
}
}
case rule == "email":
if isString && strVal != "" {
if !isValidEmail(strVal) {
return errors.New("invalid email format")
}
}
}
}
return nil
}
func isZero(v reflect.Value) bool {
return v.Interface() == reflect.Zero(v.Type()).Interface()
}
func isValidEmail(email string) bool {
return regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`).MatchString(email)
}
该函数支持多种规则组合,能处理字符串和整型字段的基本验证。通过
isZero
基本上就这些。通过反射+tag的方式,可以构建一个轻量、可扩展的验证系统,适用于大多数基础校验需求,且无需依赖外部库。实际项目中可根据需要增加更多规则如正则匹配、枚举、自定义函数等。
以上就是Golang反射结合tag实现自动验证机制的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号