Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Creating a Simple yet Powerful Struct Validation Package In Golang Without Any Reflection!
The code for Simple yet Powerful Struct Validations In Go Without Reflection:
https://ibraheem.ca/posts/golang-struct-validations
package main
import (
"encoding/json"
"net/http"
)
// POST "/users"
func Create(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
user := new(User)
json.NewDecoder(r.Body).Decode(&user)
errs := validate(user)
if errs != nil {
w.WriteHeader(http.StatusUnprocessableEntity)
json.NewEncoder(w).Encode(Stringify(errs))
return
}
}
package main
type User struct {
Email string `json:"email"`
Name string `json:"name"`
}
// validate: creates new Validator instance and calls validation methods on User fields
func validate(u *User) []error {
v := &validator.Validator{}
v.ValidatePresenceOf("Email", u.Email)
v.ValidatePresenceOf("Name", u.Name)
v.ValidateMaxLengthOf("Email", u.Email, 32)
v.ValidateMinLengthOf("Email", u.Email, 4)
emailRegex := "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
match, _ := regexp.MatchString(emailRegex, u.Email)
// email must match regex
v.Validate(match, "Email is not in valid format")
return v.Errors
}
package main
import (
"fmt"
"errors"
)
// Validator : struct field validations, holds array of errors
type Validator struct {
Errors []error
}
// Validate : validates condition, and appends error message to Validator instance if true
func (v *Validator) Validate(cond bool, msg string, args ...interface{}) {
if !cond {
v.Errors = append(v.Errors, fmt.Errorf(msg, args...))
}
}
// ValidatePresenceOf : validates presence of struct string field
func (v *Validator) ValidatePresenceOf(fieldName string, fieldValue string) {
// fieldValue must be greater than 0
cond := len(strings.TrimSpace(fieldValue)) > 0
v.Validate(cond, "%s cannot be blank", fieldName)
}
// ValidateMaxLengthOf : validates maximum character length of struct string field
func (v *Validator) ValidateMaxLengthOf(fieldName string, fieldValue string, max int) {
// fieldValue must be less than maximum
cond := len(fieldValue) < max
v.Validate(cond, "%s cannot be greater than %d characters", fieldName, max)
}
// ValidateMinLengthOf : validates minimum character length of struct string field
func (v *Validator) ValidateMinLengthOf(fieldName string, fieldValue string, min int) {
// fieldValue must be greater than minimum
cond := len(fieldValue) > min
v.Validate(cond, "%s must be at least %d characters", fieldName, min)
}
// Stringify: method to convert an array of errors to an array of strings for json response
func Stringify(errs []error) []string {
strErrors := make([]string, len(errs))
for i, err := range errs {
strErrors[i] = err.Error()
}
return strErrors
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.