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.
Slice rules validate typed slice fields defined with form.Slice.
They are useful for validating tags, categories, permissions, identifiers, selected options, API arrays, batch payloads, and other list-based application input.
Common Use Cases
Slice rules are commonly used for:
- tags and labels
- user roles and permissions
- selected categories
- batch API operations
- filter arrays
- allowed identifiers
- feature flags
- shopping cart items
- multi-select frontend forms
- configuration lists
TL;DR
| Rule | Description |
|---|---|
rules.RequiredSlice(field) | Requires the slice to contain at least one element |
rules.RequiredSliceWithCode(field, code) | Same as RequiredSlice with a custom error code |
rules.MinItems(field, n) | Requires the slice length to be at least n |
rules.MinItemsWithCode(field, n, code) | Same as MinItems with a custom error code |
rules.MaxItems(field, n) | Requires the slice length to be at most n |
rules.MaxItemsWithCode(field, n, code) | Same as MaxItems with a custom error code |
rules.ItemsBetween(field, min, max) | Requires the slice length to stay within a range |
rules.ItemsBetweenWithCode(field, min, max, code) | Same as ItemsBetween with a custom error code |
rules.ContainsItem(field, value) | Requires the slice to contain a specific item |
rules.ContainsItemWithCode(field, value, code) | Same as ContainsItem with a custom error code |
rules.UniqueItems(field) | Requires all slice items to be unique |
rules.UniqueItemsWithCode(field, code) | Same as UniqueItems with a custom error code |
rules.IsSlice(field) | Validates that the field contains a slice value |
Defining Slice Fields
Slice validation starts by defining typed slice fields.
SliceForm := struct {
Tags form.SliceField[SliceRulesRequest, string]
Permissions form.SliceField[SliceRulesRequest, string]
Ids form.SliceField[SliceRulesRequest, int]
}{
Tags: form.Slice[SliceRulesRequest]("tags", func(r *SliceRulesRequest) []string {
return r.Tags
}),
Permissions: form.Slice[SliceRulesRequest]("permissions", func(r *SliceRulesRequest) []string {
return r.Permissions
}),
Ids: form.Slice[SliceRulesRequest]("ids", func(r *SliceRulesRequest) []int {
return r.Ids
}),
}Each field contains:
- the validation response field name
- typed accessors
- reusable schema references
- strongly typed slice access
Applying Slice Rules
Slice rules are attached directly to typed field references.
return form.Schema[SliceRulesRequest]{
rules.RequiredSlice(SliceForm.Tags),
rules.MinItems(SliceForm.Tags, 1),
rules.UniqueItems(SliceForm.Permissions),
}This keeps validation logic:
- explicit
- reusable
- composable
- transport-independent
- type-safe
Rule Examples
RequiredSlice
Requires the slice to contain at least one item.
rules.RequiredSlice(SliceForm.Tags)Typical use cases:
- required categories
- selected permissions
- required batch operations
- non-empty frontend multi-selects
RequiredSliceWithCode
Requires the slice to contain items and returns a custom validation code.
const CodeTagsRequired = form.Code("tags_required")
rules.RequiredSliceWithCode(
SliceForm.Tags,
CodeTagsRequired,
)Useful for frontend-friendly API validation contracts.
MinItems
Requires the slice length to be greater than or equal to the minimum item count.
rules.MinItems(SliceForm.Tags, 2)Typical use cases:
- minimum category selection
- minimum permissions
- required batch sizes
- multi-selection validation
MinItemsWithCode
Requires the slice to contain at least the specified number of items and returns a custom validation code.
const CodeNotEnoughItems = form.Code("not_enough_items")
rules.MinItemsWithCode(
SliceForm.Tags,
2,
CodeNotEnoughItems,
)MaxItems
Requires the slice length to stay below the specified maximum.
rules.MaxItems(SliceForm.Tags, 10)Typical use cases:
- tag limits
- API payload protection
- frontend selection caps
- bounded list validation
MaxItemsWithCode
Requires the slice length to stay below the maximum and returns a custom validation code.
const CodeTooManyItems = form.Code("too_many_items")
rules.MaxItemsWithCode(
SliceForm.Tags,
10,
CodeTooManyItems,
)ItemsBetween
Requires the slice length to stay within a specified range.
rules.ItemsBetween(SliceForm.Tags, 1, 5)Typical use cases:
- bounded tag selection
- controlled multi-select input
- permission assignment validation
ItemsBetweenWithCode
Requires the slice length to stay within the specified range and returns a custom validation code.
const CodeInvalidItemCount = form.Code("invalid_item_count")
rules.ItemsBetweenWithCode(
SliceForm.Tags,
1,
5,
CodeInvalidItemCount,
)ContainsItem
Requires the slice to contain a specific item.
rules.ContainsItem(SliceForm.Permissions, "admin")Typical use cases:
- required roles
- mandatory permissions
- enforced categories
- required feature flags
ContainsItemWithCode
Requires the slice to contain a specific item and returns a custom validation code.
const CodeMissingPermission = form.Code("missing_permission")
rules.ContainsItemWithCode(
SliceForm.Permissions,
"admin",
CodeMissingPermission,
)UniqueItems
Requires all slice items to be unique.
rules.UniqueItems(SliceForm.Tags)Typical use cases:
- unique tags
- permission sets
- deduplicated identifiers
- API normalization
UniqueItemsWithCode
Requires all slice items to be unique and returns a custom validation code.
const CodeDuplicateItems = form.Code("duplicate_items")
rules.UniqueItemsWithCode(
SliceForm.Tags,
CodeDuplicateItems,
)IsSlice
Checks whether the field contains a valid slice value.
rules.IsSlice(SliceForm.Tags)For typed Go structures this rule is mostly useful for API symmetry because invalid JSON array types are typically rejected during request decoding before schema validation begins.
Complete Example
package main
import (
"github.com/netlifeguru/form"
"github.com/netlifeguru/form/rules"
)
type SliceRulesRequest struct {
Tags []string `json:"tags"`
Permissions []string `json:"permissions"`
Ids []int `json:"ids"`
}
func SliceRulesSchema() form.Schema[SliceRulesRequest] {
SliceForm := struct {
Tags form.SliceField[SliceRulesRequest, string]
Permissions form.SliceField[SliceRulesRequest, string]
Ids form.SliceField[SliceRulesRequest, int]
}{
Tags: form.Slice[SliceRulesRequest]("tags", func(r *SliceRulesRequest) []string {
return r.Tags
}),
Permissions: form.Slice[SliceRulesRequest]("permissions", func(r *SliceRulesRequest) []string {
return r.Permissions
}),
Ids: form.Slice[SliceRulesRequest]("ids", func(r *SliceRulesRequest) []int {
return r.Ids
}),
}
return form.Schema[SliceRulesRequest]{
rules.RequiredSlice(SliceForm.Tags),
rules.MinItems(SliceForm.Tags, 1),
rules.MaxItems(SliceForm.Tags, 5),
rules.UniqueItems(SliceForm.Tags),
rules.ContainsItem(SliceForm.Permissions, "admin"),
}
}Notes
- Slice rules operate on typed Go slice values.
- Invalid JSON array types are rejected before validation begins.
- Slice validation focuses on collection structure and item presence rather than individual item validation.
- Use
UniqueItemsto normalize API payloads and avoid duplicate entries. - Use
RequiredSlicewhen empty collections should be rejected explicitly. - Slice validation remains reusable across APIs, CLI tools, background workers, and internal services.
- Validation logic stays explicit and independent from HTTP or JSON transport layers.
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.
Format Rules
Learn how to validate common string formats in NLG Form, including URLs, IP addresses, UUIDs, JSON strings, and IANA timezones.