enumx

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: MIT Imports: 7 Imported by: 0

README ΒΆ

enumx logo

enumx

Define your enum once. enumx generates the type-safe Go API.

enumx is a modern, boilerplate-free enum toolkit for Go. It provides two layers of usage:

  1. Zero-Codegen Runtime Enums: Quick, flexible, generic enums constructed at runtime.
  2. AST-based Code Generation: Type-safe, struct-field based enums without writing type or const manually.

πŸš€ The Killer Feature: enumx generate

Tired of writing type Status string and defining repetitive constants? Use the AST code generator. The definition file acts as the ultimate Single Source of Truth.

1. Define your enums (once)

Create an enums.go file with the //go:build ignore directive so it is excluded from normal builds:

//go:build ignore
//go:generate enumx generate

package main

import "github.com/bakhod1r/enumx"

// Omitting the type name auto-infers it from the variable name (Status β†’ StatusType)
var Status = enumx.Define("pending", "active", "blocked")

// Or explicitly name the type as the first argument
var Roles = enumx.Define("Role", "admin", "user", "guest")

2. Generate

go install github.com/bakhod1r/enumx/cmd/enumx@latest
go generate

enumx parses the AST and writes enums_enumx_gen.go with a named type, typed constants, and a struct accessor β€” zero hand-written boilerplate.

3. Use with full type-safety

// Direct typed field access β€” IDE autocompletes every value
Status.Active    // StatusType("active")
Status.Pending   // StatusType("pending")

// Clean validation
Status.Has(Status.Active) // true

// Parse and validate external input
val, err := Status.Parse(r.FormValue("status"))
if err != nil {
    http.Error(w, err.Error(), 422)
}

πŸ—οΈ Simple Runtime Enums (no codegen)

If you just want a quick enum without code generation, use the runtime builder:

// Immutable
status := enumx.New("pending", "active", "blocked")
status.Has("active")  // true
status.Values()       // [pending active blocked]

val, _ := status.Parse("active")
val.Is("active")      // true
val.Valid()           // true
val.String()          // "active"
val.Unwrap()          // "active"

// Mutable (thread-safe)
codes := enumx.NewMutable[int]()
codes.Add(200).Add(404).Add(500)
codes.Remove(404)

Installation

go get github.com/bakhod1r/enumx

License

MIT Β© bakhod1r

Documentation ΒΆ

Index ΒΆ

Examples ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

View Source
var (
	// ErrInvalidEnum indicates that the enum value is not registered or valid.
	ErrInvalidEnum = errors.New("invalid enum value")

	// ErrEmptyEnum indicates that the enum value is empty.
	ErrEmptyEnum = errors.New("empty enum value")
)

Functions ΒΆ

func AddTransition ΒΆ

func AddTransition[T ~string](from, to T)

AddTransition is a simplified helper to register a single state transition.

func CanTransition ΒΆ

func CanTransition[T ~string](current, next T) bool

CanTransition checks if moving from the current state to the next state is a registered valid transition.

func ClearFlag ΒΆ

func ClearFlag[T Integer](mask *T, flag T)

ClearFlag clears a specific flag from a bitmask.

func Contains ΒΆ

func Contains[T ~string](val T, collection ...T) bool

Contains checks if the enum value is within the provided collection. Functionally identical to IsAny, provided for API ergonomics.

func Define ΒΆ

func Define(typeName string, values ...string) any

Define is a marker function used exclusively by the enumx-gen code generator. It should only be used in files with the `//go:build ignore` directive. The first argument is the name of the generated Go type (e.g., "Status"). The remaining arguments are the enum values.

func FormatFlags ΒΆ

func FormatFlags[T Integer](mask T) string

FormatFlags formats a bitmask into a string representation separated by " | ". If a flag is not registered, it is ignored in the output.

func HasFlag ΒΆ

func HasFlag[T Integer](mask, flag T) bool

HasFlag checks if a bitmask contains a specific flag.

func Is ΒΆ

func Is[T ~string](val, target T) bool

Is checks if the enum value is exactly equal to the target.

func IsAny ΒΆ

func IsAny[T ~string](val T, targets ...T) bool

IsAny checks if the enum value matches any of the provided targets.

func IsNot ΒΆ

func IsNot[T ~string](val, target T) bool

IsNot checks if the enum value is not equal to the target.

func IsValid ΒΆ

func IsValid[T ~string](val T) bool

IsValid checks if the provided value is a valid, registered enum value. Returns false if the value is empty, not registered, or if the type itself hasn't been registered.

func LocaleLabel ΒΆ

func LocaleLabel[T ~string](val T, locale string) string

LocaleLabel returns the localized label for an enum value given a locale code. If the locale is not found, it falls back to its raw string representation.

func MarshalJSON ΒΆ

func MarshalJSON[T ~string](v T) ([]byte, error)

MarshalJSON helps marshal an enum type T into a JSON string, ensuring it is valid. By default, Go automatically marshals underlying string types, but using this ensures invalid enum values are caught at marshal time.

Example:

func (s Status) MarshalJSON() ([]byte, error) {
    return enumx.MarshalJSON(s)
}

func Match ΒΆ

func Match[T ~string, R any](val T, cases Cases[T, R]) R

Match performs an exhaustive switch-like check over the enum value. It ensures that all registered values of T are handled in the cases map. If a case is missing for a registered enum, it panics. If the provided value itself is invalid, it also panics. This provides a runtime guarantee of exhaustiveness, catching missing cases during tests.

Example ΒΆ
package main

import (
	"fmt"

	"github.com/bakhod1r/enumx"
)

type Role string

const RoleUser Role = "user"

func (r Role) Valid() bool                   { return enumx.IsValid(r) }
func (r *Role) UnmarshalJSON(b []byte) error { return enumx.UnmarshalJSON(b, r) }
func (r Role) MarshalJSON() ([]byte, error)  { return enumx.MarshalJSON(r) }

func main() {
	role := RoleUser

	message := enumx.Match(role, enumx.Cases[Role, string]{
		RoleAdmin: func() string { return "Welcome, Admin!" },
		RoleUser:  func() string { return "Welcome, User!" },
		RoleGuest: func() string { return "Welcome, Guest!" },
	})

	fmt.Println(message)
}
Output:
Welcome, User!

func Meta ΒΆ

func Meta[T ~string, M any](val T) (M, bool)

Meta retrieves the custom metadata of type M attached to an enum value of type T. It returns the typed metadata and true if found, otherwise returns the zero value and false.

func Parse ΒΆ

func Parse[T ~string](val string) (T, error)

Parse safely parses a string into the enum type T. It validates the string against the registered values for type T. Returns ErrEmptyEnum if the input string is empty. Returns ErrInvalidEnum (wrapped with context) if the value is not registered.

Example ΒΆ
package main

import (
	"fmt"

	"github.com/bakhod1r/enumx"
)

type Role string

func (r Role) Valid() bool                   { return enumx.IsValid(r) }
func (r *Role) UnmarshalJSON(b []byte) error { return enumx.UnmarshalJSON(b, r) }
func (r Role) MarshalJSON() ([]byte, error)  { return enumx.MarshalJSON(r) }

func main() {
	role, err := enumx.Parse[Role]("admin")
	if err != nil {
		panic(err)
	}
	fmt.Println(role)
}
Output:
admin

func ParseFlags ΒΆ

func ParseFlags[T Integer](s string) (T, error)

ParseFlags parses a string separated by " | " into a bitmask of type T.

func Register ΒΆ

func Register[T ~string](values ...T)

Register registers the valid values for enum type T. This should be called in the init() function of the package where the enum is defined.

func RegisterFlags ΒΆ

func RegisterFlags[T Integer](flags map[T]string)

RegisterFlags registers the string representations for bitmask flags of type T.

func RegisterLocales ΒΆ

func RegisterLocales[T ~string](val T, locales map[string]string)

RegisterLocales registers localized labels for a specific enum value. The locales argument is a map where the key is the locale code (e.g., "en", "uz") and the value is the translated label.

Example ΒΆ
package main

import (
	"fmt"

	"github.com/bakhod1r/enumx"
)

type Role string

const RoleAdmin Role = "admin"

func (r Role) Valid() bool                   { return enumx.IsValid(r) }
func (r *Role) UnmarshalJSON(b []byte) error { return enumx.UnmarshalJSON(b, r) }
func (r Role) MarshalJSON() ([]byte, error)  { return enumx.MarshalJSON(r) }

func main() {
	enumx.RegisterLocales(RoleAdmin, map[string]string{
		"en": "Administrator",
		"uz": "Tizim ma'muri",
	})

	fmt.Println(enumx.LocaleLabel(RoleAdmin, "uz"))
	fmt.Println(enumx.LocaleLabel(RoleAdmin, "en"))
}
Output:
Tizim ma'muri
Administrator

func RegisterMeta ΒΆ

func RegisterMeta[T ~string, M any](val T, meta M)

RegisterMeta attaches custom metadata of any type M to a specific enum value of type T.

func RegisterTransitions ΒΆ

func RegisterTransitions[T ~string](transitions ...Transition[T])

RegisterTransitions registers the allowed state transitions for enum type T. This is used to build a zero-allocation finite state machine (FSM).

func Scan ΒΆ

func Scan[T ~string](src any, v *T) error

Scan helps implement the database/sql.Scanner interface. It parses the database value (typically string or []byte) into the enum type.

Example:

func (s *Status) Scan(src any) error {
    return enumx.Scan(src, s)
}

func SetFlag ΒΆ

func SetFlag[T Integer](mask *T, flag T)

SetFlag sets a specific flag in a bitmask.

func UnmarshalJSON ΒΆ

func UnmarshalJSON[T ~string](b []byte, v *T) error

UnmarshalJSON helps safely unmarshal a JSON string into an enum type T. It should be called from the UnmarshalJSON method of the custom enum type.

Example:

func (s *Status) UnmarshalJSON(b []byte) error {
    return enumx.UnmarshalJSON(b, s)
}
Example ΒΆ
package main

import (
	"encoding/json"
	"fmt"

	"github.com/bakhod1r/enumx"
)

type Role string

const (
	RoleAdmin Role = "admin"
	RoleUser  Role = "user"
	RoleGuest Role = "guest"
)

func init() {
	enumx.Register(RoleAdmin, RoleUser, RoleGuest)
}

func (r Role) Valid() bool                   { return enumx.IsValid(r) }
func (r *Role) UnmarshalJSON(b []byte) error { return enumx.UnmarshalJSON(b, r) }
func (r Role) MarshalJSON() ([]byte, error)  { return enumx.MarshalJSON(r) }

func main() {
	type Request struct {
		UserRole Role `json:"role"`
	}

	validJSON := []byte(`{"role":"admin"}`)
	var req Request
	_ = json.Unmarshal(validJSON, &req)
	fmt.Println("Parsed:", req.UserRole)

	invalidJSON := []byte(`{"role":"hacker"}`)
	var badReq Request
	err := json.Unmarshal(invalidJSON, &badReq)
	fmt.Println("Error:", err != nil)

}
Output:
Parsed: admin
Error: true

func Value ΒΆ

func Value[T ~string](v T) (driver.Value, error)

Value helps implement the database/sql/driver.Valuer interface. It validates the enum and returns its string representation.

Example:

func (s Status) Value() (driver.Value, error) {
    return enumx.Value(s)
}

func Values ΒΆ

func Values[T ~string]() []T

Values returns all registered valid values for enum type T in the order they were registered.

Types ΒΆ

type Cases ΒΆ

type Cases[T ~string, R any] map[T]func() R

Cases represents an exhaustive map of handlers for an enum type.

type Def ΒΆ

type Def[T comparable] struct {
	// contains filtered or unexported fields
}

Def is an immutable enum definition. Create it with New().

func New ΒΆ

func New[T comparable](vals ...T) *Def[T]

New creates an immutable enum definition from the provided values.

func (*Def[T]) AddTranslation ΒΆ added in v1.2.0

func (d *Def[T]) AddTranslation(loc Locale, trans map[T]string) *Def[T]

AddTranslation adds translations for a specific locale. It returns the Def instance for chaining.

func (*Def[T]) Default ΒΆ

func (d *Def[T]) Default(val T)

Default sets the default value for the enum. Panics if val is not a registered member.

func (*Def[T]) Has ΒΆ

func (d *Def[T]) Has(val T) bool

Has returns true if the value is a member of the enum.

func (*Def[T]) IsDefault ΒΆ

func (d *Def[T]) IsDefault(val T) bool

IsDefault reports whether val equals the default value.

func (*Def[T]) Parse ΒΆ

func (d *Def[T]) Parse(val T) (EnumValue[T], error)

Parse validates val and returns a Value wrapping it, or an error.

func (*Def[T]) Translate ΒΆ added in v1.2.0

func (d *Def[T]) Translate(val T, loc Locale) string

Translate returns the translation for the given value and locale. If no translation is found, it returns the string representation of the value.

func (*Def[T]) Values ΒΆ

func (d *Def[T]) Values() []T

Values returns all registered enum values in insertion order.

type Enum ΒΆ

type Enum[T ~string] struct {
	V T
}

Enum is a generic wrapper struct that provides maximum convenience. By embedding this struct in your data models, you get automatic JSON and SQL validation without writing any boilerplate methods (UnmarshalJSON, Scan, etc.).

func NewEnum ΒΆ

func NewEnum[T ~string](val T) (Enum[T], error)

NewEnum creates a new wrapped enum value safely.

func (Enum[T]) Label ΒΆ

func (e Enum[T]) Label(lang string) string

Label retrieves the localized label for the enum value if registered.

func (Enum[T]) MarshalJSON ΒΆ

func (e Enum[T]) MarshalJSON() ([]byte, error)

MarshalJSON returns the JSON string representation of the enum.

func (*Enum[T]) Scan ΒΆ

func (e *Enum[T]) Scan(src any) error

Scan implements the database/sql.Scanner interface.

func (Enum[T]) String ΒΆ

func (e Enum[T]) String() string

String returns the string representation. String returns the string representation.

func (*Enum[T]) UnmarshalJSON ΒΆ

func (e *Enum[T]) UnmarshalJSON(b []byte) error

UnmarshalJSON parses and validates the JSON string into the enum.

func (Enum[T]) Valid ΒΆ

func (e Enum[T]) Valid() bool

Valid checks if the wrapped enum value is valid.

func (Enum[T]) Value ΒΆ

func (e Enum[T]) Value() (driver.Value, error)

Value implements the database/sql/driver.Valuer interface.

type EnumValue ΒΆ

type EnumValue[T comparable] struct {
	// contains filtered or unexported fields
}

EnumValue is the result of a successful Parse call. It carries the validated value and provides a rich API.

func (EnumValue[T]) Is ΒΆ

func (v EnumValue[T]) Is(candidate T) bool

Is reports whether the value equals the given candidate.

func (EnumValue[T]) String ΒΆ

func (v EnumValue[T]) String() string

String returns the string representation of the underlying value.

func (EnumValue[T]) Unwrap ΒΆ

func (v EnumValue[T]) Unwrap() T

Unwrap returns the underlying value.

func (EnumValue[T]) Valid ΒΆ

func (v EnumValue[T]) Valid() bool

Valid reports whether this value was successfully parsed from an enum.

type FlagSet ΒΆ

type FlagSet[T ~uint] struct {
	V T
}

FlagSet is a wrapper for bitmask enums to provide a clean OOP API.

func (*FlagSet[T]) Add ΒΆ

func (f *FlagSet[T]) Add(flag T)

Add sets the specified flag.

func (FlagSet[T]) Has ΒΆ

func (f FlagSet[T]) Has(flag T) bool

Has returns true if the specified flag is set.

func (*FlagSet[T]) Remove ΒΆ

func (f *FlagSet[T]) Remove(flag T)

Remove clears the specified flag.

func (FlagSet[T]) String ΒΆ

func (f FlagSet[T]) String() string

String returns the string representation of the set flags.

type Integer ΒΆ

type Integer interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}

Integer defines a constraint that permits any integer type. This is used for bitmask flags.

type Locale ΒΆ added in v1.2.0

type Locale string

Locale represents a language locale for enum translations. Custom locales can be defined by casting a string to Locale, e.g. enumx.Locale("kk").

const (
	EN  Locale = "en"  // English
	ZH  Locale = "zh"  // Chinese
	HI  Locale = "hi"  // Hindi
	ES  Locale = "es"  // Spanish
	FR  Locale = "fr"  // French
	AR  Locale = "ar"  // Arabic
	BN  Locale = "bn"  // Bengali
	RU  Locale = "ru"  // Russian
	PT  Locale = "pt"  // Portuguese
	UR  Locale = "ur"  // Urdu
	ID  Locale = "id"  // Indonesian
	DE  Locale = "de"  // German
	JA  Locale = "ja"  // Japanese
	MR  Locale = "mr"  // Marathi
	TE  Locale = "te"  // Telugu
	TR  Locale = "tr"  // Turkish
	TA  Locale = "ta"  // Tamil
	YUE Locale = "yue" // Cantonese
	VI  Locale = "vi"  // Vietnamese
	TL  Locale = "tl"  // Tagalog
	KO  Locale = "ko"  // Korean
	FA  Locale = "fa"  // Persian
	HA  Locale = "ha"  // Hausa
	SW  Locale = "sw"  // Swahili
	JV  Locale = "jv"  // Javanese
	IT  Locale = "it"  // Italian
	PA  Locale = "pa"  // Punjabi
	GU  Locale = "gu"  // Gujarati
	TH  Locale = "th"  // Thai
	AM  Locale = "am"  // Amharic
	KN  Locale = "kn"  // Kannada
	BHO Locale = "bho" // Bhojpuri
	NAN Locale = "nan" // Min Nan Chinese
	MY  Locale = "my"  // Burmese
	HAK Locale = "hak" // Hakka Chinese
	YOR Locale = "yor" // Yoruba
	UZ  Locale = "uz"  // Uzbek
	OR  Locale = "or"  // Odia
	MAI Locale = "mai" // Maithili
	SD  Locale = "sd"  // Sindhi
	UK  Locale = "uk"  // Ukrainian
	IG  Locale = "ig"  // Igbo
	NL  Locale = "nl"  // Dutch
	PL  Locale = "pl"  // Polish
	KU  Locale = "ku"  // Kurdish
	SN  Locale = "sn"  // Shona
	RO  Locale = "ro"  // Romanian
	AZ  Locale = "az"  // Azerbaijani
	HU  Locale = "hu"  // Hungarian
	CS  Locale = "cs"  // Czech
	EL  Locale = "el"  // Greek
	SV  Locale = "sv"  // Swedish
	BE  Locale = "be"  // Belarusian
	BG  Locale = "bg"  // Bulgarian
	KK  Locale = "kk"  // Kazakh
	SR  Locale = "sr"  // Serbian
	FI  Locale = "fi"  // Finnish
	SK  Locale = "sk"  // Slovak
	DA  Locale = "da"  // Danish
	NO  Locale = "no"  // Norwegian
	HE  Locale = "he"  // Hebrew
	LT  Locale = "lt"  // Lithuanian
	SL  Locale = "sl"  // Slovenian
	ET  Locale = "et"  // Estonian
	LV  Locale = "lv"  // Latvian
	HY  Locale = "hy"  // Armenian
	KA  Locale = "ka"  // Georgian
	IS  Locale = "is"  // Icelandic
	GA  Locale = "ga"  // Irish
	CY  Locale = "cy"  // Welsh
	MT  Locale = "mt"  // Maltese
	SQ  Locale = "sq"  // Albanian
	MK  Locale = "mk"  // Macedonian
	BS  Locale = "bs"  // Bosnian
	HR  Locale = "hr"  // Croatian
	MS  Locale = "ms"  // Malay
	KM  Locale = "km"  // Khmer
	LO  Locale = "lo"  // Lao
	NE  Locale = "ne"  // Nepali
	SI  Locale = "si"  // Sinhala
	TG  Locale = "tg"  // Tajik
	TK  Locale = "tk"  // Turkmen
	KY  Locale = "ky"  // Kyrgyz
	MN  Locale = "mn"  // Mongolian
	PS  Locale = "ps"  // Pashto
	TI  Locale = "ti"  // Tigrinya
	SO  Locale = "so"  // Somali
	RW  Locale = "rw"  // Kinyarwanda
	NY  Locale = "ny"  // Chichewa
	ST  Locale = "st"  // Southern Sotho
	TN  Locale = "tn"  // Tswana
	XH  Locale = "xh"  // Xhosa
	ZU  Locale = "zu"  // Zulu
	AF  Locale = "af"  // Afrikaans
	EU  Locale = "eu"  // Basque
	CA  Locale = "ca"  // Catalan
	GL  Locale = "gl"  // Galician
	HT  Locale = "ht"  // Haitian Creole
	GD  Locale = "gd"  // Scottish Gaelic
	MI  Locale = "mi"  // Maori
)

Standard language locales (top 100+)

type Matcher ΒΆ

type Matcher[T ~string, R any] struct {
	// contains filtered or unexported fields
}

Matcher is a builder for exhaustive matching.

func MatchBuilder ΒΆ

func MatchBuilder[T ~string, R any](val T) *Matcher[T, R]

MatchBuilder creates a new Matcher builder for exhaustive evaluation. You must specify the return type R: enumx.MatchBuilder[Status, string](val)

func (*Matcher[T, R]) Case ΒΆ

func (m *Matcher[T, R]) Case(c T, handler func() R) *Matcher[T, R]

Case adds a handler for a specific enum case.

func (*Matcher[T, R]) Must ΒΆ

func (m *Matcher[T, R]) Must() R

Must evaluates the match and panics if the case is not handled.

type MutableDef ΒΆ

type MutableDef[T comparable] struct {
	// contains filtered or unexported fields
}

MutableDef is a thread-safe, mutable enum definition. Create it with NewMutable().

func NewMutable ΒΆ

func NewMutable[T comparable](vals ...T) *MutableDef[T]

NewMutable creates a thread-safe, mutable enum definition.

func (*MutableDef[T]) Add ΒΆ

func (d *MutableDef[T]) Add(val T) *MutableDef[T]

Add appends val to the enum. Returns self for chaining.

func (*MutableDef[T]) AddTranslation ΒΆ added in v1.2.0

func (d *MutableDef[T]) AddTranslation(loc Locale, trans map[T]string) *MutableDef[T]

AddTranslation adds translations for a specific locale. It returns the MutableDef instance for chaining.

func (*MutableDef[T]) Default ΒΆ

func (d *MutableDef[T]) Default(val T)

Default sets the default value for the enum.

func (*MutableDef[T]) Has ΒΆ

func (d *MutableDef[T]) Has(val T) bool

Has returns true if the value is a member of the mutable enum.

func (*MutableDef[T]) IsDefault ΒΆ

func (d *MutableDef[T]) IsDefault(val T) bool

IsDefault reports whether val equals the default value.

func (*MutableDef[T]) Parse ΒΆ

func (d *MutableDef[T]) Parse(val T) (EnumValue[T], error)

Parse validates val and returns a Value wrapping it, or an error.

func (*MutableDef[T]) Remove ΒΆ

func (d *MutableDef[T]) Remove(val T) *MutableDef[T]

Remove deletes val from the enum. Returns self for chaining.

func (*MutableDef[T]) Translate ΒΆ added in v1.2.0

func (d *MutableDef[T]) Translate(val T, loc Locale) string

Translate returns the translation for the given value and locale. If no translation is found, it returns the string representation of the value.

func (*MutableDef[T]) Values ΒΆ

func (d *MutableDef[T]) Values() []T

Values returns all registered enum values in insertion order.

type Transition ΒΆ

type Transition[T ~string] struct {
	From T
	To   T
}

Transition represents a valid state transition from one enum value to another.

Directories ΒΆ

Path Synopsis
cmd
enumx command
example
basic command
codegen command
Code generated by enumx.
Code generated by enumx.
generate command
Code generated by enumx.
Code generated by enumx.
http-api command
Code generated by enumx.
Code generated by enumx.
usage command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL