Golang, a strong-typed language allows the ability to group constants together in parenthesis with the iota
keyword. But coupling that with a string representation can add extra boilerplate code. Let’s first take a look at how constants and enums are created in Go.
A recap on constants and enums in Go…
For example, as constants by placing them in parenthesis:
const ( Dog = 0 Cat = 1 Bird = 2 )
Using the iota
keyword to make an enum:
const ( Dog = iota Cat Bird
Using the iota
with a declared constant type:
type Animal int const ( Dog Animal = iota Cat Bird )
All the above examples would output the same values with the latter being typed as Animal. Let’s take a look at the last example and the expected output:
package main import "fmt" type Animal int const ( Dog Animal = iota Cat Bird ) func main() { fmt.Println(Dog) // would output 0 fmt.Println(Bird) // would output 2 }
Adding a string representation with Stringer
Based on the Golang/Tools docs… “Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer. Given the name of a (signed or unsigned) integer type T that has constants defined, stringer will create a new self-contained Go source file implementing func (t T) String() string
”
In other words, String will give us string representations of “Dog, Cat and Bird” depending on our constant value.
To use Stringer your constants must be declared in a package other than main
which is typically not an issue in most programs since you’re creating constants to be exportable.
Let’s define our constants again in an animal
package and provide examples on using Stringer.
package animal type Animal int const ( Dog Animal = iota Cat Bird )
Running stringer -type=Animal
in the same package directory would generate a file called animal_string.go
, containing the definition:
func (Animal) String() string
To simplify this in larger projects you can add the go-generate
comments in the animal
package as //go:generate stringer -type=Animal
which would create the animal_string.go
without the need of running this in each package directory.
Let’s take a look at what a Stringer based enumeration would output:
package main import ( "fmt" "animal" ) func main() { fmt.Println(animal.Dog) // would output "Dog" fmt.Println(animal.Cat) // would output "Cat" fmt.Println(animal.Dog == 0) // would output true }
Hopefully, this quick write-up can provide you with extra tricks to create user-friendly enum based constants. The full GoDoc on stringer.