Advanced Examples
Explore more powerful features and use cases for goenums.
Extended Enum Types with Custom Fields
Add custom fields to your enums using 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
//go:generate goenums planets.go
const (
unknown planet = iota // invalid
mercury // Mercury 0.378,2439.7,3.3e23,57910000
venus // Venus 0.907,6051.8,4.87e24,108200000
earth // Earth 1,6378.1,5.97e24,149600000
mars // Mars 0.377,3389.5,6.42e23,227900000
// ...
)
After generation, 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)
// Get the radius of Earth
fmt.Printf("Earth radius: %.1f km\n", solarsystem.Planets.EARTH.RadiusKm)
JSON, Text, Binary, YAML, and Database Storage
The generated enum type implements the:
json.Marshaler
andjson.Unmarshaler
interfacessql.Scanner
andsql.Valuer
interfacesencoding.BinaryMarshaler
andencoding.BinaryUnmarshaler
interfacesencoding.TextMarshaler
andencoding.TextUnmarshaler
interfacesyaml.Marshaler
andyaml.Unmarshaler
interfaces
These interfaces allow you to use the enum type in JSON, text, binary, YAML, and database storage seamlessly.
// JSON example
type Mission struct {
ID int `json:"id"`
Destination solarsystem.Planet `json:"destination"`
}
mission := Mission{
ID: 1,
Destination: solarsystem.Planets.MARS,
}
// Marshals to {"id":1,"destination":"Mars"}
jsonData, _ := json.Marshal(mission)
// Database example
func SaveMission(db *sql.DB, mission Mission) error {
_, err := db.Exec("INSERT INTO missions (id, destination) VALUES (?, ?)",
mission.ID, mission.Destination)
return err
}
// The Planet type will be stored as "Mars" in the database
Exhaustive Handling
Use exhaustive handling function to ensure you handle all enum values with the generated Exhaustive
function:
// Process all enum values safely
// This is especially useful in tests to ensure all enum values are covered
validation.ExhaustiveTicketStatuses(func(status validation.TicketStatus) {
// Process each status
switch status {
case validation.TicketStatuses.FAILED:
handleFailed()
case validation.TicketStatuses.PASSED:
handlePassed()
// ...
}
})
// We can also iterate over all enum values to do exhaustive calculations
weightKg := 100.0
solarsystem.ExhaustivePlanets(func(p solarsystem.Planet) {
// calculate weight on each planet
gravity := p.Gravity
planetMass := weightKg * gravity
fmt.Printf("Weight on %s is %fKg with gravity %f\n", p, planetMass, gravity)
})
Failfast Mode / Strict Mode
Enable strict validation of enum values with the failfast flag:
//go:generate goenums -f status.go
Generated code will return errors for invalid values:
status, err := validation.ParseStatus("INVALID_STATUS")
if err != nil {
fmt.Println("error:", err)
}
Legacy vs Modern Mode
Choose between modern Go 1.23+ iterator support and legacy iteration styles.
// Modern iteration (Go 1.23+)
// Using Go 1.23+ range-over-function iteration
for status := range validation.Statuses.All() {
fmt.Printf("Status: %s\n", status)
}
// Legacy iteration (or with -l flag)
// Using a slice of all enum values
for _, status := range validation.Statuses.All() {
fmt.Printf("Status: %s\n", status)
}
Constraints Mode
Generate local type constraints instead of importing external dependencies:
//go:generate goenums -c status.go
// Generated code will include local constraint definitions:
type float interface {
float32 | float64
}
type integer interface {
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr
}
type number interface {
integer | float
}
Compile-time Validation
The generated code includes compile-time validation to ensure enum values remain consistent:
// Compile-time check that all enum values are valid.
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the goenums command to generate them again.
var x [7]struct{}
_ = x[unknown-0]
_ = x[failed-1]
_ = x[passed-2]
// ... other enum values
}
This ensures that if you change the order or values of your enum constants, you’ll get a compile error reminding you to regenerate the enum code.