Skip to Content

Validators

The validators package provides input validation built on go-playground/validator/v10 . It uses struct tag-based validation with custom validators registered at startup, and produces translated error messages.

Import

import "github.com/gofastadev/gofasta/pkg/validators"

Key Types

AppValidator

type AppValidator struct { Validate *validator.Validate Trans ut.Translator }

Key Functions

FunctionSignatureDescription
NewAppValidatorfunc NewAppValidator(db *gorm.DB) *AppValidatorCreates a validator with common validations registered
ValidateStructfunc (v *AppValidator) ValidateStruct(input interface{}) []*types.TCommonAPIErrorDtoValidates the input struct and returns validation errors
RegisterCommonValidatorsfunc RegisterCommonValidators(validate *validator.Validate, db *gorm.DB)Registers the gofasta library’s common validators on an existing validator instance
RegisterTranslationfunc RegisterTranslation(v *validator.Validate, trans ut.Translator, tag string, message string)Registers a custom validation error message

Built-in Custom Validators

These validators are registered automatically when using NewAppValidator and can be used as struct tags:

TagDescription
uuid4_validMust be a valid UUID v4
is_record_deletableRecord must be deletable (checks is_deletable column)
is_record_exist_by_name_for_conflictName must not already exist in the specified table
does_record_exist_by_id_for_verificationID must exist in the specified table
is_valid_urlMust be a valid HTTP or HTTPS URL

In addition, all standard go-playground/validator tags are available (required, email, min, max, gte, lte, etc.).

Usage

Setting Up the Validator

The AppValidator is created once at startup and shared across your application:

appValidator := validators.NewAppValidator(db)

Defining Validation with Struct Tags

type CreateUserInput struct { Name string `json:"name" validate:"required,min=2,max=100"` Email string `json:"email" validate:"required,email"` Password string `json:"password" validate:"required,min=8"` Role string `json:"role" validate:"required,oneof=admin editor viewer"` Website *string `json:"website" validate:"omitempty,is_valid_url"` }

Validating in a Controller

func (c *UserController) Create(w http.ResponseWriter, r *http.Request) { var input CreateUserInput if err := httputil.Bind(r, &input); err != nil { httputil.Error(w, errors.BadRequest(err.Error())) return } if valErrs := c.validator.ValidateStruct(input); len(valErrs) > 0 { httputil.JSON(w, http.StatusBadRequest, types.TCommonResponseDto{ Status: http.StatusBadRequest, Errors: valErrs, }) return } user, err := c.service.Create(r.Context(), input) if err != nil { httputil.Error(w, err) return } httputil.Created(w, user) }

The error response looks like:

{ "status": 400, "errors": [ {"fieldName": "email", "message": "Email must be a valid email address"}, {"fieldName": "password", "message": "Password must be at least 8 characters in length"} ] }

Database Uniqueness Check

Use the is_record_exist_by_name_for_conflict tag with the table name as a parameter:

type CreateCategoryInput struct { Name string `json:"name" validate:"required,is_record_exist_by_name_for_conflict=categories"` }

Record Existence Verification

type AssignRoleInput struct { RoleID string `json:"roleId" validate:"required,uuid4_valid,does_record_exist_by_id_for_verification=roles"` }

Registering Custom Validators

Extend the validator by registering additional validations on the Validate field:

appValidator := validators.NewAppValidator(db) // Register a custom validation appValidator.Validate.RegisterValidation("strong_password", func(fl validator.FieldLevel) bool { password := fl.Field().String() hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(password) hasLower := regexp.MustCompile(`[a-z]`).MatchString(password) hasDigit := regexp.MustCompile(`[0-9]`).MatchString(password) return hasUpper && hasLower && hasDigit }) // Register a translation for the custom validation validators.RegisterTranslation(appValidator.Validate, appValidator.Trans, "strong_password", "{0} must contain uppercase, lowercase, and digit characters")

Then use it in struct tags:

type ResetPasswordInput struct { Password string `json:"password" validate:"required,min=8,strong_password"` }
  • Errors — Validation errors map to structured error responses
  • HTTP Utilities — Bind and validate request input
  • Types — Shared DTO types including TCommonAPIErrorDto
Last updated on