package validate import ( "fmt" "strings" ) // ValidationError 用于收集多个字段错误,同时实现 error 接口 type ValidationError struct { Errors map[string]string } // Error 实现 error 接口 func (v *ValidationError) Error() string { msgs := make([]string, 0, len(v.Errors)) for field, err := range v.Errors { msgs = append(msgs, fmt.Sprintf("%s: %s", field, err)) } return strings.Join(msgs, "; ") } // NotEmpty 校验 map[string]interface{} 中指定字段不能为空 func NotEmpty(data map[string]interface{}, fields ...string) error { errs := make(map[string]string) for _, field := range fields { collectErrors(data[field], field, errs) } if len(errs) > 0 { return &ValidationError{Errors: errs} } return nil } // collectErrors 递归收集字段错误 func collectErrors(v interface{}, path string, errs map[string]string) { if v == nil { errs[path] = "字段不能为空" return } switch val := v.(type) { case string: if strings.TrimSpace(val) == "" { errs[path] = "字段不能为空" } case []interface{}: if len(val) == 0 { errs[path] = "字段不能为空" } for i, elem := range val { collectErrors(elem, fmt.Sprintf("%s[%d]", path, i), errs) } case map[string]interface{}: if len(val) == 0 { errs[path] = "字段不能为空" } for k, elem := range val { collectErrors(elem, fmt.Sprintf("%s.%s", path, k), errs) } default: // 其他类型暂不校验 } }