NetLife Guru

Open source Go packages for fast, maintainable web systems. Built with a documentation-first approach.

Product
OverviewGolang packagesNews
Documentation
DocumentationGo LoggerGo RouterGo DB Form
Company
OverviewContactNewsGitHub
Community / Support
Supportinfo@netlife.guru
© 2026 NetLife Guru. All rights reserved.
GitHubinfo@netlife.guru
NetLife GuruNetLife GuruNetLife Guru
NetLife GuruNetLife GuruNetLife Guru
OverviewDocumentationNewsSupportContact

Golang packages

About
Validation RulesBoolean RulesFloat64 RulesInteger RulesString RulesTime RulesRequired RulesSlice RulesFormat RulesGeneric RulesCompare Rules
Form ValidatorRules

Generic Rules

Learn how to validate generic comparable values in NLG Form using reusable allowed-value rules for strings, integers, booleans, enums, statuses, plans, and custom validation codes.

Generic rules validate typed comparable fields through reusable value constraints.

They are useful when a field must match one of a predefined set of allowed values, such as roles, statuses, plans, priorities, levels, feature states, or enum-like application values.

Common Use Cases

Generic rules are commonly used for:

  • user roles
  • publishing statuses
  • subscription plans
  • enum-like values
  • priority levels
  • configuration states
  • feature flags
  • workflow states
  • allowed numeric values
  • fixed API contracts

TL;DR

RuleDescription
rules.OneOf(field, allowed...)Requires the field value to match one of the allowed values
rules.OneOfWithCode(field, code, allowed...)Same as OneOf with a custom error code

Defining Generic Fields

Generic rules work with any comparable field value.

GenericForm := struct {
	Role   form.StringField[GenericRulesRequest]
	Level  form.IntField[GenericRulesRequest]
	Active form.BoolField[GenericRulesRequest]
}{
	Role: form.Str[GenericRulesRequest]("role", func(r *GenericRulesRequest) string {
		return r.Role
	}),
	Level: form.Int[GenericRulesRequest]("level", func(r *GenericRulesRequest) int {
		return r.Level
	}),
	Active: form.Bool[GenericRulesRequest]("active", func(r *GenericRulesRequest) bool {
		return r.Active
	}),
}

Generic rules use the underlying field through .Field:

GenericForm.Role.Field

This allows the same rule to work with different comparable value types.

Applying Generic Rules

Use OneOf when a value must be part of a fixed allowed set.

return form.Schema[GenericRulesRequest]{
	rules.OneOf[GenericRulesRequest, string](
		GenericForm.Role.Field,
		"admin",
		"editor",
		"viewer",
	),

	rules.OneOf[GenericRulesRequest, int](
		GenericForm.Level.Field,
		1,
		2,
		3,
	),

	rules.OneOf[GenericRulesRequest, bool](
		GenericForm.Active.Field,
		true,
	),
}

Rule Examples

OneOf

Requires the field value to match one of the allowed values.

rules.OneOf[GenericRulesRequest, string](
	GenericForm.Role.Field,
	"admin",
	"editor",
	"viewer",
)

Typical use cases:

  • allowed roles
  • enum-like string values
  • predefined workflow states
  • controlled API input

OneOf with Integers

OneOf can also validate integer values.

rules.OneOf[GenericRulesRequest, int](
	GenericForm.Level.Field,
	1,
	2,
	3,
)

Typical use cases:

  • priority levels
  • fixed numeric states
  • allowed configuration values
  • numeric enum-like input

OneOf with Booleans

OneOf can validate boolean values as well.

rules.OneOf[GenericRulesRequest, bool](
	GenericForm.Active.Field,
	true,
)

This is useful when a boolean value must explicitly match a required state.


OneOfWithCode

Requires the field value to match one of the allowed values and returns a custom validation code.

const CodeInvalidStatus = form.Code("invalid_status")

rules.OneOfWithCode[GenericRulesRequest, string](
	GenericForm.Status.Field,
	CodeInvalidStatus,
	"draft",
	"published",
	"archived",
)

Custom codes are useful for frontend translations, stable API contracts, and consistent validation responses.

Complete Example

package main

import (
	"github.com/netlifeguru/form"
	"github.com/netlifeguru/form/rules"
)

const (
	CodeInvalidStatus   = form.Code("invalid_status")
	CodeInvalidPlan     = form.Code("invalid_plan")
	CodeInvalidPriority = form.Code("invalid_priority")
)

type GenericRulesRequest struct {
	Role     string `json:"role"`
	Status   string `json:"status"`
	Plan     string `json:"plan"`
	Level    int    `json:"level"`
	Priority int    `json:"priority"`
	Active   bool   `json:"active"`
}

func GenericRulesSchema() form.Schema[GenericRulesRequest] {
	GenericForm := struct {
		Role     form.StringField[GenericRulesRequest]
		Status   form.StringField[GenericRulesRequest]
		Plan     form.StringField[GenericRulesRequest]
		Level    form.IntField[GenericRulesRequest]
		Priority form.IntField[GenericRulesRequest]
		Active   form.BoolField[GenericRulesRequest]
	}{
		Role: form.Str[GenericRulesRequest]("role", func(r *GenericRulesRequest) string {
			return r.Role
		}),
		Status: form.Str[GenericRulesRequest]("status", func(r *GenericRulesRequest) string {
			return r.Status
		}),
		Plan: form.Str[GenericRulesRequest]("plan", func(r *GenericRulesRequest) string {
			return r.Plan
		}),
		Level: form.Int[GenericRulesRequest]("level", func(r *GenericRulesRequest) int {
			return r.Level
		}),
		Priority: form.Int[GenericRulesRequest]("priority", func(r *GenericRulesRequest) int {
			return r.Priority
		}),
		Active: form.Bool[GenericRulesRequest]("active", func(r *GenericRulesRequest) bool {
			return r.Active
		}),
	}

	return form.Schema[GenericRulesRequest]{
		rules.OneOf[GenericRulesRequest, string](
			GenericForm.Role.Field,
			"admin",
			"editor",
			"viewer",
		),

		rules.OneOfWithCode[GenericRulesRequest, string](
			GenericForm.Status.Field,
			CodeInvalidStatus,
			"draft",
			"published",
			"archived",
		),

		rules.OneOfWithCode[GenericRulesRequest, string](
			GenericForm.Plan.Field,
			CodeInvalidPlan,
			"free",
			"pro",
			"enterprise",
		),

		rules.OneOf[GenericRulesRequest, int](
			GenericForm.Level.Field,
			1,
			2,
			3,
		),

		rules.OneOfWithCode[GenericRulesRequest, int](
			GenericForm.Priority.Field,
			CodeInvalidPriority,
			10,
			20,
			30,
		),

		rules.OneOf[GenericRulesRequest, bool](
			GenericForm.Active.Field,
			true,
		),
	}
}

Notes

  • Generic rules work with comparable Go values.
  • OneOf is useful for enum-like validation without introducing custom enum types.
  • Use OneOfWithCode for public APIs that require stable error codes.
  • Empty values are still validated unless optional or conditional logic is used.
  • Generic rules use the underlying field through .Field.
  • For specialized validation, prefer type-specific rules such as string, integer, boolean, time, or format rules.
  • Generic validation remains explicit, reusable, and independent from HTTP or JSON transport layers.

Format Rules

Learn how to validate common string formats in NLG Form, including URLs, IP addresses, UUIDs, JSON strings, and IANA timezones.

Compare Rules

Learn how to compare fields in NLG Form using equality, inequality, greater-than, less-than, and cross-field validation rules.

On this page

Common Use CasesTL;DRDefining Generic FieldsApplying Generic RulesRule ExamplesOneOfOneOf with IntegersOneOf with BooleansOneOfWithCodeComplete ExampleNotes