Type safe enums for Go without code generation or reflection
[ 📄 docs ] [ 🐙 github ] [ ❤️ sponsor ]
Type safe enums for Go without code generation or reflection.
😎 Features:
go get github.com/orsinium-labs/enum
Define:
type Color enum.Member[string]
var (
Red = Color{"red"}
Green = Color{"green"}
Blue = Color{"blue"}
Colors = enum.New(Red, Green, Blue)
)
Parse a raw value (nil
is returned for invalid value):
parsed := Colors.Parse("red")
Compare enum members:
parsed == Red
Red != Green
Accept enum members as function arguments:
func SetPixel(x, i int, c Color)
Loop over all enum members:
for _, color := range Colors.Members() {
// ...
}
Ensure that the enum member belongs to an enum (can be useful for defensive programming to ensure that the caller doesn't construct an enum member manually):
func f(color Color) {
if !colors.Contains(color) {
panic("invalid color")
}
// ...
}
Define custom methods on enum members:
func (c Color) UnmarshalJSON(b []byte) error {
return nil
}
Dynamically create enums to pass multiple members in a function:
func SetPixel2(x, y int, colors enum.Enum[Color, string]) {
if colors.Contains(Red) {
// ...
}
}
purple := enum.New(Red, Blue)
SetPixel2(0, 0, purple)
Enum members can be any comparable type, not just strings:
type ColorValue struct {
UI string
DB int
}
type Color enum.Member[ColorValue]
var (
Red = Color{ColorValue{"red", 1}}
Green = Color{ColorValue{"green", 2}}
Blue = Color{ColorValue{"blue", 3}}
Colors = enum.New(Red, Green, Blue)
)
fmt.Println(Red.Value.UI)
If the enum has lots of members and new ones may be added over time, it's easy to forget to register all members in the enum. To prevent this, use enum.Builder to define an enum:
type Color enum.Member[string]
var (
b = enum.NewBuilder[string, Color]()
Red = b.Add(Color{"red"})
Green = b.Add(Color{"green"})
Blue = b.Add(Color{"blue"})
Colors = b.Enum()
)