Implement enumerated types in Go using iota and constants
Enumerated types (enums) are types with a fixed number of possible values, each with a distinct name. Go doesn’t have an enum type as a distinct language feature, but enums are simple to implement using existing language idioms.
package mainimport "fmt"// Our enum type ServerState has an underlying int type.type ServerState int// The possible values for ServerState are defined as constants.// The special keyword iota generates successive constant values// automatically; in this case 0, 1, 2 and so on.const ( StateIdle ServerState = iota StateConnected StateError StateRetrying)func main() { ns := transition(StateIdle) fmt.Println(ns) ns2 := transition(ns) fmt.Println(ns2)}// transition emulates a state transition for a server;// it takes the existing state and returns a new state.func transition(s ServerState) ServerState { switch s { case StateIdle: return StateConnected case StateConnected, StateRetrying: return StateIdle case StateError: return StateError default: panic(fmt.Errorf("unknown state: %s", s)) }}
Implement the fmt.Stringer interface to make your enum values readable:
// By implementing the fmt.Stringer interface, values of ServerState// can be printed out or converted to strings.var stateName = map[ServerState]string{ StateIdle: "idle", StateConnected: "connected", StateError: "error", StateRetrying: "retrying",}func (ss ServerState) String() string { return stateName[ss]}
Output:
connectedidle
For types with many possible values, the stringer tool can be used with go:generate to automate creating the String() method. See this post for details.
Using a custom type provides compile-time type safety:
func transition(s ServerState) ServerState { // ...}// ✓ This workstransition(StateIdle)// ✗ This won't compile - type mismatch// transition(1)// If we had used plain int:// func transition(s int) int { ... }// Both would work, losing type safety
By defining a custom type like ServerState, you get compile-time type checking. You can’t accidentally pass a plain int to functions expecting a ServerState.