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

Compare Rules

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

Compare rules validate relationships between two fields.

They are useful when one field depends on another field or when values must match specific relational constraints.

Common Use Cases

Compare rules are commonly used for:

  • password confirmation
  • start and end date validation
  • minimum and maximum values
  • pricing constraints
  • score comparison
  • quantity validation
  • numeric ranges
  • matching identifiers
  • workflow transitions
  • ordered application state

TL;DR

RuleDescription
rules.Compare(a, b, rules.OpEQ)Requires a == b
rules.Compare(a, b, rules.OpNE)Requires a != b
rules.Compare(a, b, rules.OpLT)Requires a < b
rules.Compare(a, b, rules.OpLTE)Requires a <= b
rules.Compare(a, b, rules.OpGT)Requires a > b
rules.Compare(a, b, rules.OpGTE)Requires a >= b
rules.CompareWithCode(a, b, op, code)Same as Compare with a custom error code

Supported Types

Compare rules support ordered comparable values:

  • strings
  • integers
  • unsigned integers
  • float32 / float64

This allows cross-field validation across common application data types.

Comparison Operators

OperatorDescription
rules.OpEQEqual
rules.OpNENot equal
rules.OpLTLess than
rules.OpLTELess than or equal
rules.OpGTGreater than
rules.OpGTEGreater than or equal

Defining Comparable Fields

Compare validation starts by defining typed fields.

CompareForm := struct {
	Password        form.StringField[CompareRequest]
	ConfirmPassword form.StringField[CompareRequest]

	MinPrice form.IntField[CompareRequest]
	MaxPrice form.IntField[CompareRequest]
}{
	Password: form.Str[CompareRequest]("password", func(r *CompareRequest) string {
		return r.Password
	}),
	ConfirmPassword: form.Str[CompareRequest]("confirm_password", func(r *CompareRequest) string {
		return r.ConfirmPassword
	}),

	MinPrice: form.Int[CompareRequest]("min_price", func(r *CompareRequest) int {
		return r.MinPrice
	}),
	MaxPrice: form.Int[CompareRequest]("max_price", func(r *CompareRequest) int {
		return r.MaxPrice
	}),
}

Compare rules operate on the underlying field definitions:

CompareForm.Password.Field

This allows reusable cross-field validation logic.

Applying Compare Rules

Compare rules validate relationships between two field values.

return form.Schema[CompareRequest]{
	rules.Compare(
		CompareForm.Password.Field,
		CompareForm.ConfirmPassword.Field,
		rules.OpEQ,
	),

	rules.Compare(
		CompareForm.MinPrice.Field,
		CompareForm.MaxPrice.Field,
		rules.OpLTE,
	),
}

Rule Examples

Equal (OpEQ)

Requires both values to be equal.

rules.Compare(
	CompareForm.Password.Field,
	CompareForm.ConfirmPassword.Field,
	rules.OpEQ,
)

Typical use cases:

  • password confirmation
  • repeated email fields
  • matching identifiers
  • confirmation workflows

Not Equal (OpNE)

Requires both values to be different.

rules.Compare(
	CompareForm.CurrentPassword.Field,
	CompareForm.NewPassword.Field,
	rules.OpNE,
)

Typical use cases:

  • password changes
  • unique configuration values
  • preventing duplicated state

Less Than (OpLT)

Requires the first value to be less than the second value.

rules.Compare(
	CompareForm.MinPrice.Field,
	CompareForm.MaxPrice.Field,
	rules.OpLT,
)

Typical use cases:

  • price ranges
  • pagination windows
  • scoring systems
  • numeric boundaries

Less Than or Equal (OpLTE)

Requires the first value to be less than or equal to the second value.

rules.Compare(
	CompareForm.MinPrice.Field,
	CompareForm.MaxPrice.Field,
	rules.OpLTE,
)

Useful for inclusive ranges and bounded validation.


Greater Than (OpGT)

Requires the first value to be greater than the second value.

rules.Compare(
	CompareForm.MaxPrice.Field,
	CompareForm.MinPrice.Field,
	rules.OpGT,
)

Typical use cases:

  • increasing values
  • score progression
  • upper boundary validation

Greater Than or Equal (OpGTE)

Requires the first value to be greater than or equal to the second value.

rules.Compare(
	CompareForm.MaxPrice.Field,
	CompareForm.MinPrice.Field,
	rules.OpGTE,
)

Useful for inclusive upper bounds.


CompareWithCode

Adds a custom validation code to compare validation failures.

const CodePasswordsMismatch = form.Code("passwords_mismatch")

rules.CompareWithCode(
	CompareForm.Password.Field,
	CompareForm.ConfirmPassword.Field,
	rules.OpEQ,
	CodePasswordsMismatch,
)

Custom error codes are useful for frontend validation contracts and standardized API responses.

Schema Example

package main

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

const (
	CodePasswordsMismatch = form.Code("passwords_mismatch")
	CodeInvalidRange      = form.Code("invalid_range")
)

type CompareRequest struct {
	Password        string `json:"password"`
	ConfirmPassword string `json:"confirm_password"`

	MinPrice int `json:"min_price"`
	MaxPrice int `json:"max_price"`
}

func CompareSchema() form.Schema[CompareRequest] {
	CompareForm := struct {
		Password        form.StringField[CompareRequest]
		ConfirmPassword form.StringField[CompareRequest]

		MinPrice form.IntField[CompareRequest]
		MaxPrice form.IntField[CompareRequest]
	}{
		Password: form.Str[CompareRequest]("password", func(r *CompareRequest) string {
			return r.Password
		}),
		ConfirmPassword: form.Str[CompareRequest]("confirm_password", func(r *CompareRequest) string {
			return r.ConfirmPassword
		}),

		MinPrice: form.Int[CompareRequest]("min_price", func(r *CompareRequest) int {
			return r.MinPrice
		}),
		MaxPrice: form.Int[CompareRequest]("max_price", func(r *CompareRequest) int {
			return r.MaxPrice
		}),
	}

	return form.Schema[CompareRequest]{
		rules.CompareWithCode(
			CompareForm.Password.Field,
			CompareForm.ConfirmPassword.Field,
			rules.OpEQ,
			CodePasswordsMismatch,
		),

		rules.CompareWithCode(
			CompareForm.MinPrice.Field,
			CompareForm.MaxPrice.Field,
			rules.OpLTE,
			CodeInvalidRange,
		),
	}
}

HTTP Example

main.go

package main

import (
	"encoding/json"
	"fmt"
	"log/slog"
	"net/http"
	"os"

	"github.com/netlifeguru/form"
	"github.com/netlifeguru/form/httpform"
	"github.com/netlifeguru/router"
)

func main() {
	r := router.New()

	r.HandleFunc("/compare-rules", "POST", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		var in CompareRequest

		if !httpform.BindAndValidate(w, req, &in, CompareSchema(), 1<<20) {
			fmt.Println("compare validation failed")
			return
		}

		fmt.Println("compare validation passed:", in)

		w.Header().Set("Content-Type", "application/json")

		_ = json.NewEncoder(w).Encode(map[string]any{
			"message": "compare validation passed",
			"data":    in,
		})
	})

	validPayload := map[string]any{
		"password":         "secret123",
		"confirm_password": "secret123",
		"min_price":        10,
		"max_price":        100,
	}

	invalidPayload := map[string]any{
		"password":         "secret123",
		"confirm_password": "secret321",
		"min_price":        100,
		"max_price":        10,
	}

	fmt.Println("\n--- Valid request ---")
	form.SendTestPost(":8080/compare-rules", validPayload)

	fmt.Println("\n--- Invalid request ---")
	form.SendTestPost(":8080/compare-rules", invalidPayload)

	if err := r.ListenAndServe(8080); err != nil {
		slog.Error("failed to start server", "error", err)
		os.Exit(1)
	}
}

Notes

  • Compare rules validate relationships between two field values.
  • Validation errors are attached to the first field passed into the comparison.
  • Compare rules work with ordered comparable values.
  • Compare validation is useful for cross-field consistency and bounded ranges.
  • Unknown comparison operators always fail validation.
  • Custom validation codes are recommended for frontend-facing APIs.
  • Compare validation remains explicit and independent from HTTP or JSON transport layers.

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.

Optional Validation

Learn how optional validation works in NLG Form using OptionalString, OptionalPtr, OptionalSlice, nullable fields, and conditional validation pipelines.

On this page

Common Use CasesTL;DRSupported TypesComparison OperatorsDefining Comparable FieldsApplying Compare RulesRule ExamplesEqual (OpEQ)Not Equal (OpNE)Less Than (OpLT)Less Than or Equal (OpLTE)Greater Than (OpGT)Greater Than or Equal (OpGTE)CompareWithCodeSchema ExampleHTTP Examplemain.goNotes