Required Rules
Learn how required validation works in NLG Form, how empty values are handled, and why required rules change validation behavior for optional and zero-value fields.
Required rules are one of the most important concepts in form.
Unlike many traditional validators that implicitly validate zero values, form treats empty values differently depending on whether a field is marked as required.
This behavior is intentional.
Validation Philosophy
In form, validation rules are generally skipped for empty values unless the field is explicitly marked as required.
This means:
- empty strings
- zero-value numbers
- zero
time.Time - nil optional values
- missing optional fields
are typically ignored by non-required validation rules.
This allows schemas to naturally support optional fields without forcing every validation rule to handle empty-state logic manually.
Why Required Rules Matter
Required rules change validation behavior.
Once a field is marked as required:
- the field must exist
- the field must contain a non-empty value
- additional validation rules are executed normally
Without a required rule:
rules.MinLen(UserForm.Name, 5)an empty value:
{
"name": ""
}is silently ignored.
With a required rule:
rules.Required(UserForm.Name)the same payload becomes invalid.
This allows validation pipelines to distinguish between:
- optional fields
- required fields
- partially validated fields
without additional conditional logic.
Common Use Cases
Required rules are commonly used for:
- registration forms
- login requests
- billing information
- required API payloads
- onboarding workflows
- mandatory profile fields
- password reset requests
- configuration validation
TL;DR
| Rule | Description |
|---|---|
rules.Required(field) | Requires a non-empty string value |
rules.RequiredWithCode(field, code) | Same as Required with a custom error code |
rules.RequiredInt(field) | Requires a non-zero integer value |
rules.RequiredIntWithCode(field, code) | Same as RequiredInt with a custom error code |
rules.RequiredFloat64(field) | Requires a non-zero float64 value |
rules.RequiredFloat64WithCode(field, code) | Same as RequiredFloat64 with a custom error code |
rules.RequiredBool(field) | Requires the boolean field to be present |
rules.RequiredBoolWithCode(field, code) | Same as RequiredBool with a custom error code |
rules.RequiredTime(field) | Requires a non-zero time.Time value |
rules.RequiredTimeWithCode(field, code) | Same as RequiredTime with a custom error code |
Required String Fields
String fields are considered empty when the value is:
""Example:
rules.Required(UserForm.Name)Typical use cases:
- usernames
- emails
- passwords
- required text input
RequiredWithCode
const CodeNameRequired = form.Code("name_required")
rules.RequiredWithCode(
UserForm.Name,
CodeNameRequired,
)Useful for frontend-facing validation APIs and stable error contracts.
Required Integer Fields
Integer fields are considered empty when the value is:
0Example:
rules.RequiredInt(UserForm.Age)Typical use cases:
- required counters
- quantities
- identifiers
- pagination input
RequiredIntWithCode
const CodeAgeRequired = form.Code("age_required")
rules.RequiredIntWithCode(
UserForm.Age,
CodeAgeRequired,
)Required Float64 Fields
Float64 fields are considered empty when the value is:
0.0Example:
rules.RequiredFloat64(PaymentForm.Amount)Typical use cases:
- payment amounts
- pricing
- measurements
- decimal configuration values
RequiredFloat64WithCode
const CodeAmountRequired = form.Code("amount_required")
rules.RequiredFloat64WithCode(
PaymentForm.Amount,
CodeAmountRequired,
)Required Boolean Fields
Boolean fields behave differently from strings and numeric values.
Because false is a valid boolean value, required boolean validation checks whether the field exists and was provided during decoding.
Example:
rules.RequiredBool(SettingsForm.Accepted)Typical use cases:
- required consent flags
- explicit feature toggles
- mandatory user decisions
RequiredBoolWithCode
const CodeConsentRequired = form.Code("consent_required")
rules.RequiredBoolWithCode(
SettingsForm.Accepted,
CodeConsentRequired,
)Required Time Fields
Time fields are considered empty when the value is:
time.Time{}Example:
rules.RequiredTime(EventForm.StartAt)Typical use cases:
- booking dates
- expiration timestamps
- scheduled events
- required deadlines
RequiredTimeWithCode
const CodeStartDateRequired = form.Code("start_date_required")
rules.RequiredTimeWithCode(
EventForm.StartAt,
CodeStartDateRequired,
)Validation Behavior
Required rules affect how subsequent rules behave.
Example:
form.Schema[UserRequest]{
rules.Required(UserForm.Name),
rules.MinLen(UserForm.Name, 5),
}Validation flow:
| Input | Result |
|---|---|
"" | Fails Required |
"abc" | Fails MinLen |
"abcdef" | Passes |
Without Required:
form.Schema[UserRequest]{
rules.MinLen(UserForm.Name, 5),
}Validation flow:
| Input | Result |
|---|---|
"" | Ignored |
"abc" | Fails MinLen |
"abcdef" | Passes |
This distinction is one of the core design principles of form.
Complete Example
package main
import (
"time"
"github.com/netlifeguru/form"
"github.com/netlifeguru/form/rules"
)
type RequiredRequest struct {
Name string `json:"name"`
Age int `json:"age"`
Amount float64 `json:"amount"`
Accepted bool `json:"accepted"`
StartAt time.Time `json:"start_at"`
}
func RequiredSchema() form.Schema[RequiredRequest] {
RequiredForm := struct {
Name form.StringField[RequiredRequest]
Age form.IntField[RequiredRequest]
Amount form.Float64Field[RequiredRequest]
Accepted form.BoolField[RequiredRequest]
StartAt form.TimeField[RequiredRequest]
}{
Name: form.Str[RequiredRequest]("name", func(r *RequiredRequest) string {
return r.Name
}),
Age: form.Int[RequiredRequest]("age", func(r *RequiredRequest) int {
return r.Age
}),
Amount: form.Float64[RequiredRequest]("amount", func(r *RequiredRequest) float64 {
return r.Amount
}),
Accepted: form.Bool[RequiredRequest]("accepted", func(r *RequiredRequest) bool {
return r.Accepted
}),
StartAt: form.Time[RequiredRequest]("start_at", func(r *RequiredRequest) time.Time {
return r.StartAt
}),
}
return form.Schema[RequiredRequest]{
rules.Required(RequiredForm.Name),
rules.RequiredInt(RequiredForm.Age),
rules.RequiredFloat64(RequiredForm.Amount),
rules.RequiredBool(RequiredForm.Accepted),
rules.RequiredTime(RequiredForm.StartAt),
}
}Notes
- Required rules change validation behavior for empty values.
- Non-required validation rules generally ignore empty values.
- This design allows schemas to naturally support optional fields without additional conditional logic.
RequiredBooldiffers from other required rules becausefalseis a valid boolean value.- Required validation remains explicit and transport-independent.
- Required rules are usually the first rules applied within a schema.
- This validation model helps separate optional and mandatory input cleanly in larger applications and APIs.
Time Rules
Learn how to validate time.Time fields in NLG Form using before, after, range, equality, zero-value, and custom validation rules.
Slice Rules
Learn how to validate slice and array fields in NLG Form using length validation, emptiness checks, containment rules, uniqueness validation, and custom error codes.