Skip to content

Validation

goose provides a powerful validation engine built into schemas. Validation rules run automatically and ensure your data maintains integrity before hitting the database.

Built-in Validators

goose includes several built-in validators that you can configure via FieldDef or struct tags:

  • Required: Ensures a field is non-zero/non-empty.
  • Min/Max: Validates numeric bounds.
  • MinLength/MaxLength: Validates string lengths.
  • Enum: Restricts a value to a specific set of allowed values.
  • Match: Validates a string against a regular expression.
fields := map[string]goose.FieldDef{
    "email": {
        Required: true,
        Match:    `^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`,
    },
    "age": {
        Min: 18.0,
        Max: 120.0,
    },
    "role": {
        Enum: []interface{}{"admin", "user", "guest"},
    },
}

Custom Validators

If the built-in validators aren't enough, you can define a custom ValidatorFn. A ValidatorFn takes the value and returns an error if validation fails.

fields := map[string]goose.FieldDef{
    "username": {
        Validate: func(value interface{}) error {
            str, ok := value.(string)
            if !ok {
                return fmt.Errorf("must be a string")
            }
            if str == "admin" {
                return fmt.Errorf("username 'admin' is reserved")
            }
            return nil
        },
    },
}

Handling Validation Errors

When validation fails, goose returns a *ValidationErrors error containing details about every field that failed. You can inspect it to build helpful API responses.

type ValidationError struct {
    Field   string
    Message string
    Value   interface{}
    Kind    string
}

Struct Tags vs FieldDefs

goose supports extracting validation rules from the goose:"" struct tag (e.g., goose:"required,min=18"). Refer to the main README for an example.