Last active
May 28, 2019 14:47
-
-
Save creachadair/e115971699d247415ec7ae91dccfc340 to your computer and use it in GitHub Desktop.
A mechanism for representing enumerations in Go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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