Goenums
Type Safe Enum generator for Go
Install / Use
/learn @zarldev/GoenumsREADME
goenums
goenums addresses Go's lack of native enum support by generating comprehensive, type-safe enum implementations from simple constant declarations. Transform basic iota based constants into feature-rich enums with string conversion, validation, JSON handling, database integration, and more.
Installation
go install github.com/zarldev/goenums@latest
Documentation
Documentation is available at https://zarldev.github.io/goenums.
Table of Contents
- Key Features
- Usage
- Features Expanded
- Custom String Representations
- Extended Enum Types with Custom Fields
- Case Insensitive String Parsing
- JSON, Text, Binary, YAML, and Database Storage
- Numeric Parsing Support
- Exhaustive Handling
- Iterator Support (Go 1.23+)
- Failfast Mode / Strict Mode
- Legacy Mode
- Verbose Mode
- Constraints Mode
- Output Format
- Compile-time Validation
- Getting Started
- Requirements
- Examples
- License
Key Features
- Type Safety: Wrapper types prevent accidental misuse of enum values
- String Conversion: Automatic string representation and parsing
- JSON Support: Built-in marshaling and unmarshaling
- YAML Support: Built-in YAML marshaling and unmarshaling
- Database Integration: SQL Scanner and Valuer implementations
- Text/Binary Marshaling: Support for encoding.TextMarshaler/TextUnmarshaler and BinaryMarshaler/BinaryUnmarshaler
- Numeric Parsing: Parse enums from various numeric types (int, float, etc.)
- Validation: Methods to check for valid enum values
- Iteration: Modern Go 1.23+ iteration support with legacy fallback
- Extensibility: Add custom fields to enums via comments
- Exhaustive Handling: Helper functions to ensure you handle all enum values
- Alias Support: Alternative enum names via comment syntax
- Zero Dependencies: Completely dependency-free, using only the Go standard library
Usage
$ goenums -h
____ _____ ___ ____ __ ______ ___ _____
/ __ '/ __ \/ _ \/ __ \/ / / / __ '__ \/ ___/
/ /_/ / /_/ / __/ / / / /_/ / / / / / (__ )
\__, /\____/\___/_/ /_/\__,_/_/ /_/ /_/____/
/____/
Usage: goenums [options] file.go[,file2.go,...]
Options:
-c
-constraints
Specify whether to generate the float and integer constraints or import 'golang.org/x/exp/constraints' (default: false - imports)
-f
-failfast
Enable failfast mode - fail on generation of invalid enum while parsing (default: false)
-h
-help
Print help information
-i
-insensitive
Generate case insensitive string parsing (default: false)
-l
-legacy
Generate legacy code without Go 1.23+ iterator support (default: false)
-o string
-output string
Specify the output format (default: go)
-v
-version
Print version information
-vv
-verbose
Enable verbose mode - prints out the generated code (default: false)
Features Expanded
Custom String Representations
Handle custom string representations defined in the comments of each enum. Support for enum strings with spaces is supported by adding the alternative name in double quotes:
Standard Name Comment
When the Alternative name does not contain spaces there is no need to add the double quotes.
type status int
//go:generate goenums -f -c status.go
const (
unknown status = iota // invalid UNKNOWN
failed // FAILED
passed // PASSED
skipped // SKIPPED
scheduled // SCHEDULED
running // RUNNING
booked // BOOKED
)
Name Comment with spaces
When using Alternative names that contain spaces, the double quotes are required.
type order int
//go:generate goenums status.go
const (
created order = iota // "CREATED"
approved // "APPROVED"
processing // "PROCESSING"
readyToShip // "READY TO SHIP"
shipped // "SHIPPED TO CUSTOMER"
delivered // "DELIVERED TO CUSTOMER"
cancelled // "CANCELLED BY CUSTOMER"
refunded // "REFUNDED TO CUSTOMER"
closed // "CLOSED"
)
Extended Enum Types with Custom Fields
Add custom fields to your enums with type comments:
// Define fields in the type comment using one of three formats:
// 1. Space-separated: "Field Type,AnotherField Type"
// 2. Brackets: "Field[Type],AnotherField[Type]"
// 3. Parentheses: "Field(Type),AnotherField(Type)"
type planet int // Gravity float64,RadiusKm float64,MassKg float64,OrbitKm float64,OrbitDays float64,SurfacePressureBars float64,Moons int,Rings bool
//go:generate goenums planets.go
const (
mercury planet = iota // Mercury 0.378,2439.7,3.3e23,57910000,88,0.0000000001,0,false
venus // Venus 0.907,6051.8,4.87e24,108200000,225,92,0,false
earth // Earth 1,6378.1,5.97e24,149600000,365,1,1,false
mars // Mars 0.377,3389.5,6.42e23,227900000,687,0.01,2,false
jupiter // Jupiter 2.36,69911,1.90e27,778600000,4333,20,4,true
saturn // Saturn 0.916,58232,5.68e26,1433500000,10759,1,7,true
uranus // Uranus 0.889,25362,8.68e25,2872500000,30687,1.3,13,true
neptune // Neptune 1.12,24622,1.02e26,4495100000,60190,1.5,2,true
)
Then we can use the extended enum type:
earthWeight := 100.0
fmt.Printf("Weight on %s: %.2f kg\n",
solarsystem.Planets.MARS,
earthWeight * solarsystem.Planets.MARS.Gravity)
Case Insensitive String Parsing
Use the -i flag to enable case insensitive string parsing:
//go:generate goenums -i status.go
// Generated code will parse case insensitive strings. All
// of the below will validate and produce the 'PASSED' enum
status, err := validation.ParseStatus("PASSED")
if err != nil {
fmt.Println("error:", err)
}
status, err := validation.ParseStatus("passed")
if err != nil {
fmt.Println("error:", err)
}
status, err := validation.ParseStatus("Passed")
if err != nil {
fmt.Println("error:", err)
}
JSON, Text, Binary, YAML, and Database Storage
The generated enum type also implements several common interfaces:
json.Marshalerandjson.Unmarshalersql.Scannerandsql.Valuerencoding.TextMarshalerandencoding.TextUnmarshalerencoding.BinaryMarshalerandencoding.BinaryUnmarshaler
These interfaces are used to handle parsing for JSON, Text, Binary, and Database storage using the common standard library packages.
As there is no standard library support for YAML, the generated YAML marshaling and unmarshaling methods are based on the * yaml.Marshaler and yaml.Unmarshaler interfaces from the goccy/go-yaml module.
Here is an example of the generated handling code:
// MarshalJSON implements the json.Marshaler interface for Status.
// It returns the JSON representation of the enum value as a byte slice.
func (p Status) MarshalJSON() ([]byte, error) {
return []byte("\"" + p.String() + "\""), nil
}
// UnmarshalJSON implements the json.Unmarshaler interface for Status.
// It parses the JSON representation of the enum value from the byte slice.
// It returns an error if the input is not a valid JSON representation.
func (p *Status) UnmarshalJSON(b []byte) error {
b = bytes.Trim(bytes.Trim(b, "\""), "\"")
newp, err := ParseStatus(b)
if err != nil {
return err
}
*p = newp
return nil
}
// MarshalText implements the encoding.TextMarshaler interface for Status.
// It returns the string representation of the enum value as a byte slice
func (p Status) MarshalText() ([]byte, error) {
return []byte("\"" + p.String() + "\""), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface for Status.
// It parses the string representation of the enum value from the byte slice.
// It returns an error if the byte slice does not contain a valid enum value.
func (p *Status) UnmarshalText(b []byte) error {
newp, err := ParseStatus(b)
if err != nil {
return err
}
*p = newp
return nil
}
// Scan implements the database/sql.Scanner interface for Status.
// It parses the string representation of the enum value from the database row.
// It returns an error if the row does not contain a valid enum value.
func (p *Status) Scan(value any) error {
newp, err := ParseStatus(value)
if err != nil {
return err
}
*p = newp
return nil
}
// Value implements the database/sql/driver.Valuer interface for Status.
// It returns the string representation of the enum value.
func (p Status) Value() (driver.Value, error) {
return p.String(), nil
}
// MarshalBinary implements the encoding.BinaryMarshaler interface for Status.
// It returns the binary representation of the enum value as a byte slice.
func (p Status) MarshalBinary() ([]byte, error) {
return []byte("\"" + p.String() + "\""), nil
}
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface for Status.
// It parse
