Skip to content

Instantly share code, notes, and snippets.

@creachadair
Last active May 28, 2019 14:47
Show Gist options
  • Select an option

  • Save creachadair/e115971699d247415ec7ae91dccfc340 to your computer and use it in GitHub Desktop.

Select an option

Save creachadair/e115971699d247415ec7ae91dccfc340 to your computer and use it in GitHub Desktop.
A mechanism for representing enumerations in Go
// See also: https://play.golang.org/p/2Bbde-p2MBx
package enum
import "fmt"
// A common way to represent enumerations in Go is to define a type
// whose structure is int, char, string, bool, etc. That has the
// virtue of being simple, but has some deficiencies, viz.
//
// 1. Untyped constants compatible with the structure type may be assigned
// to locations of the enumeration type without a conversion, which
// voids much of the benefit of having the enumeration as a distinct
// type.
//
// 2. If the underlying structure is not a string, you have to do extra
// work to generate a String method for the type, e.g., using the
// https://godoc.org/golang.org/x/tools/cmd/stringer tool.
//
// Here is an alternative representation that avoids those problems.
// In this representation, an enumerator is identified by a pointer
// to its string. Comparing enumerator values is fast, just a pointer
// comparison, and the only invalid value is an uninitialized one.
type Enum struct{ *string }
func (e Enum) String() string {
if e.string == nil {
return "<void>"
}
return *e.string
}
var (
es = []string{"YES", "NO", "AUTO"}
// Define the enumerators.
Invalid = Enum{}
Yes = Enum{&es[0]}
No = Enum{&es[1]}
Auto = Enum{&es[2]}
)
func main() {
var inv Enum
fmt.Print("\t", Yes, "\t", No, "\t", Auto, "\t", Invalid, "\n")
for _, a := range []Enum{Yes, No, Auto, inv} {
fmt.Print(a)
for _, b := range []Enum{Yes, No, Auto, Invalid} {
fmt.Print("\t", b == a)
}
fmt.Println()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment