package validate import ( "fmt" "reflect" "github.com/go-playground/validator/v10" "pkg.local/utils" ) // ValidatorMessages 自定义错误消息 type ValidatorMessages map[string]string // IValidator 业务结构体实现该接口 type IValidator interface { GetMessage() ValidatorMessages } var v *validator.Validate func init() { v = validator.New() } // CopySameField 反射自动拷贝同名字段:src(proto入参) → dst(校验model结构体指针) // src: proto message对象,传值in // dst: model校验结构体指针 &model.AdminGroupValidator{} func CopySameField(src interface{}, dst interface{}) { srcVal := reflect.ValueOf(src) dstVal := reflect.ValueOf(dst).Elem() // 如果src是指针,取element if srcVal.Kind() == reflect.Ptr { srcVal = srcVal.Elem() } for i := 0; i < srcVal.NumField(); i++ { srcField := srcVal.Field(i) fieldName := srcVal.Type().Field(i).Name // 查找dst中同名的字段 dstField := dstVal.FieldByName(fieldName) if !dstField.IsValid() || !dstField.CanSet() { continue } // 类型相同才赋值 if srcField.Type() == dstField.Type() { dstField.Set(srcField) } } } // ValidateStruct 校验,返回 *admin.Response func ValidateStruct(obj IValidator) string { err := v.Struct(obj) if err == nil { return utils.StringEmpty } customMsg := obj.GetMessage() var errMsg string if ves, ok := err.(validator.ValidationErrors); ok { ve := ves[0] key := fmt.Sprintf("%s.%s", ve.Field(), ve.Tag()) if msg, exist := customMsg[key]; exist { errMsg = msg } else { errMsg = fmt.Sprintf("%s校验失败:%s", ve.Field(), ve.Tag()) } } else { errMsg = err.Error() } return errMsg } // ValidateFromProto 一步到位:自动拷贝proto同名字段 + 校验 // src: proto请求 in (*admin.XXXRequest) // dst: model校验结构体实例指针 &model.AdminGroupValidator{} func ValidateFromProto(src interface{}, dst IValidator) string { CopySameField(src, dst) return ValidateStruct(dst) }