- How enums work
iota
(not itoa
)
- See also
stringer
doc
- Enums are relatively annoying to use
- Compare to Rust enum or to Java enum
- eg. does the compiler enforce switch statements are comprehensive? (not for golang)
- eg. can the enum have properties? (not for golang)
- iota is a constant
- only works inside a
const
declaration
- Starts at
0
(not 1
)
- Zero value is
UnknownFoo
- Suffix
Unknown
with distinct type to void collision with other enums in the package
type GameDirection uint8
const (
UnknownDirection = GameDirection(iota)
Up
Down
Left
Right
)
// Helper method example
func (d GameDirection) IsHorizontal() bool {
switch d {
case Left, Right:
return true
default:
//NOTE: Unknown case is here
return false
}
}
- Pro: simpler to maintain than
switch
approach
- Pro: simpler reverse lookups
- Pro: (sligtly) less code
- Con: Indirect lookups
var directionLabels = map[GameDirection]string{
Down: "Down",
Left: "Left",
Right: "Right",
Up: "Up",
}
// NOTE: You can also generate these via stringer program
// signature matches fmt.Stringer interface
func (d GameDirection) String() string {
s, ok := directionLabels[d]
if !ok {
return "N/A"
}
return s
}
- Pro: Faster than
map
approach
- Con: harder to maintain
- Con: harder to do reverse lookups
// signature matches fmt.Stringer interface
func (d GameDirection) String() string {
switch d {
case Down:
return "Down"
case Left:
return "Left"
case Right:
return "Right"
case Up:
return "Up"
default:
return "N/A"
}
}
func FromLabel(label string) GameDirection {
candidate := strings.TrimSpace(label)
for key, lbl := range directionLabels {
if strings.EqualFold(lbl, candidate) {
return key
}
}
return Unknown
}
func FromValue(value uint8) GameDirection {
switch GameDirection(value) {
case Down:
return Down
case Left:
return Left
case Right:
return Right
case Up:
return Up
default:
return Unknown
}
}
- Prefer unsigned numeric type
- Declare a new type (not an alias)
- Compiler distinguishes from other enums
- Start with
Unknown
(as zero value)
- Helps detect unset value
- Helps integrate with gRPC and Protocol Buffers
- TODO: catching missing branches in enum switch
- Official docs
- https://threedots.tech/post/safer-enums-in-go/
- https://dlintw.github.io/gobyexample/public/constants-and-iota.html
- https://yourbasic.org/golang/iota/
- https://www.practical-go-lessons.com/chap-27-enum-iota-and-bitmask
- https://golangbyexample.com/iota-in-golang/
- https://medium.com/swlh/iota-create-effective-constants-in-golang-b399f94aac31