Created
December 31, 2025 22:49
-
-
Save joshbedo/39a60ac929dd76fd216d612a39c56a3a to your computer and use it in GitHub Desktop.
Validate structs using reflections
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // You can edit this code! | |
| // Click here and start typing. | |
| package main | |
| import ( | |
| "fmt" | |
| "reflect" | |
| "strconv" | |
| "strings" | |
| ) | |
| type User struct { | |
| Name string `validate:"min=2,max=12"` | |
| Email string `validate:"required,email"` | |
| } | |
| func validateMinLength( | |
| rule string, | |
| field reflect.Value, | |
| fieldName string, | |
| ) error { | |
| //fmt.Println(rule, field, fieldName) | |
| min, _ := strconv.Atoi( | |
| strings.TrimPrefix(rule, "min="), | |
| ) | |
| if len(field.String()) < min { | |
| return fmt.Errorf( | |
| "%s must be at least %d characters long", | |
| fieldName, | |
| min, | |
| ) | |
| } | |
| return nil | |
| } | |
| func validateMaxLength( | |
| rule string, | |
| field reflect.Value, | |
| fieldName string, | |
| ) error { | |
| fmt.Println(rule, field, fieldName) | |
| return nil | |
| } | |
| func applyRule( | |
| rule string, | |
| field reflect.Value, | |
| fieldName string, | |
| ) error { | |
| switch { | |
| case strings.HasPrefix(rule, "min="): | |
| return validateMinLength(rule, field, fieldName) | |
| case strings.HasPrefix(rule, "max="): | |
| return validateMaxLength(rule, field, fieldName) | |
| // case strings.HasPrefix(rule, "max="): | |
| // max, _ := strconv.Atoi( | |
| // strings.TrimPrefix(rule, "max="), | |
| // ) | |
| // if len(field.String()) > max { | |
| // return fmt.Errorf( | |
| // "%s must be less than %d characters long", | |
| // fieldName, | |
| // max, | |
| // ) | |
| // } | |
| // case rule == "required": | |
| // if field.String() == "" { | |
| // return fmt.Errorf( | |
| // "%s is required", | |
| // fieldName, | |
| // ) | |
| // } | |
| // case rule == "email": | |
| // _, err := mail.ParseAddress(field.String()) | |
| // if err != nil { | |
| // return fmt.Errorf( | |
| // "%s must be a valid email address", | |
| // fieldName, | |
| // ) | |
| } | |
| return nil | |
| } | |
| func validate(val interface{}) error { | |
| v := reflect.ValueOf(val) | |
| for i := 0; i < v.NumField(); i++ { | |
| field := v.Field(i) | |
| tag := v.Type().Field(i).Tag.Get("validate") | |
| fieldName := v.Type().Field(i).Name | |
| if tag == "" { | |
| continue | |
| } | |
| rules := strings.Split(tag, ",") | |
| for _, rule := range rules { | |
| if err := applyRule(rule, field, fieldName); err != nil { | |
| return err | |
| } | |
| } | |
| } | |
| return nil | |
| } | |
| func main() { | |
| user := User{ | |
| Name: "Josh", | |
| Email: "josh@gmail.com", | |
| } | |
| fmt.Println(validate(user)) | |
| invalidUser := User{ | |
| Name: "a", | |
| Email: "joshm", | |
| } | |
| fmt.Println(validate(invalidUser)) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment