★ Ultimate Visual Guide to Go Enums
Go enums and iota — Full of tips and tricks with runnable code examples.
Important: In this tutorial, you’ll learn how to use the enums without iota in the first section — After that, you’ll also learn about iota and the other helper tools as well after the first section. So, learn to crawl first, then walk then run!


What is an Enum? ★
An enum groups related constants together in one type.
Example enums:
- Timezones: EST, CST…
- T-shirt Sizes: Small, Medium, Large
- Server Statuses: Unknown, Running, Stopped, Resumed

Why do we need enums?
- Grouping and expecting only some related values
- Sharing common behavior
- Avoids using invalid values
- To increase the code readability and the maintainability

How can you imitate an enum in Go?
For example, suppose that you want to create an enum for the weekdays.



★ First: Declare a new custom type: Weekday
Weekday will unify our enum constants under a common type.
type Weekday int

★ Second: Declare related constants for Weekday
Assign them different numeric values, so, they don’t clash.
const (
Sunday Weekday = 0
Monday Weekday = 1
Tuesday Weekday = 2
Wednesday Weekday = 3
Thursday Weekday = 4
Friday Weekday = 5
Saturday Weekday = 6
)
// will display 0
fmt.Println(Sunday)
// will display 6
fmt.Println(Saturday)

Creating common behavior for Weekday enum
You attach methods to a type to define its behaviors.
The attached methods will be the inseparable parts of Weekday, and shared among Weekday constants.



★ String() method:
func (day Weekday) String() string {
// declare an array of strings
// ... operator counts how many
// items in the array (7)
names := [...]string{
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"}// → `day`: It's one of the
// values of Weekday constants.
// If the constant is Sunday,
// then day is 0.
// prevent panicking in case of
// `day` is out of range of Weekday
if day < Sunday || day > Saturday {
return "Unknown"
}
// return the name of a Weekday
// constant from the names array
// above.
return names[day]
}
★ Let’s try:
fmt.Printf("Which day it is? %s\n",
Sunday)
// Which day it is? Sunday
★ Weekend() method:
func (day Weekday) Weekend() bool {
switch day {
// If day is a weekend day:
case Sunday, Saturday:
return true// If day is not a weekend day:
default:
return false
}
}
Convention: Instead of IsWeekend, we just use Weekend.
★ Let’s try:
fmt.Printf("Is Saturday a weekend day? %t\n", Saturday.Weekend())
// Is Saturday a weekend day? true
Creating names automatically


You can use Rob Pike’s Stringer to create String method automatically.
# install the stringer tool
go get -u -a golang.org/x/tools/cmd/stringer# grab the code from here
# and save it in weekday.go
# inside your $GOPATH/src/enums
# then, run stringer to create
# enum names automatically
stringer -type Weekday weekdays.go
You can also use other tools like: jsonenums (created by Francesc Campoy) or enumer (created by Álvaro López).

Automate enum values with: iota
→ A numeric universal counter starting at 0
→ Used only withconstantdeclarations
→ Can be shadowed. Please, don’t do that.

How to use iota?
Iota expression is repeated by the other constants until another assignment or type declaration shows up.



Let’s see how iota ticks tocks
iota increases by 1 after each line except empty and comment lines.



When not to use iota
const (
RestartMarkerReply = 110
ServiceReadyInNMinutes = 120
CommandOK = 200
CommandNotImplemented = 202
// ...
)
Don’t use iota for a list of predefined values like FTP server status codes.
const (
Fatal = iota
)
Just assign 0 there. It’s harmless but it’s unnecessary either.



This section will enhance your understanding of iota.

A basic expression
type Timezone int
const (
// iota: 0, EST: -5
EST Timezone = -(5 + iota)
// iota: 1, CST: -6
CST
// iota: 2, MST: -7
MST
// iota: 3, MST: -8
PST
)

Resetting iota
// iota reset: it will be 0.
const (
Zero = iota // Zero = 0
One // One = 1
)
// iota reset: will be 0 again
const (
Two = iota // Two = 0
)
// iota: reset
const Three = iota // Three = 0

Skipping some values
type Timezone int
const (
// iota: 0, EST: -5
EST Timezone = -(5 + iota)
// _ is the blank identifier
// iota: 1
_
// iota: 2, MST: -7
MST
// iota: 3, MST: -8
PST
)

About iota’s behavior on comment and empty lines
type Timezone int
const (
// iota: 0, EST: -5
EST Timezone = -(5 + iota)
// On a comment or an empty
// line, iota will not
// increase
// iota: 1, CST: -6
CST
// iota: 2, MST: -7
MST
// iota: 3, MST: -8
PST
)

Using iota in the middle
const (
One = 1
Two = 2
// Three = 2 + 1 => 3
// iota in the middle
Three = iota + 1
// Four = 3 + 1 => 4
Four
)

Multiple iotas in a single line
const (
// Active = 0, Moving = 0,
// Running = 0
Active, Moving, Running = iota, iota, iota
// Passive = 1, Stopped = 1,
// Stale = 1
Passive, Stopped, Stale
)
In the same line, all constants will get the same iota values.
const (
// Active = 0, Running = 100
Active, Running = iota, iota + 100
// Passive = 1, Stopped = 101
Passive, Stopped
// You can't declare like this.
// The last expression will be
// repeated
CantDeclare
// But, you can reset
// the last expression
Reset = iota
// You can use any other
// expression even without iota
AnyOther = 10
)

Repeating and cancelling expressions
const (
// iota: 0, One: 1 (type: int64)
One int64 = iota + 1
// iota: 1, Two: 2 (type: int64)
// Two will be declared as if:
// Two int64 = iota + 1
Two
// iota: 2, Four: 4 (type: int32)
Four int32 = iota + 2
// iota: 3, Five: 5 (type: int32)
// Five will be declared as if:
// Five int32 = iota + 2
Five
// (type: int)
Six = 6
// (type: int)
// Seven will be declared as if:
// Seven = 6
Seven
)
The last used expression and type will be repeated.

Evens and odds
type Even bool
const (
// 0 % 2 == 0 ==> Even(true)
a = Even(iota % 2 == 0)
// 1 % 2 == 0 ==> Even(false)
b
// 2 % 2 == 0 ==> Even(true)
c
// 3 % 2 == 0 ==> Even(false)
d
)
=` operator converts the iota expression to bool type.
Counting backwards
const (
max = 10
)
const (
a = (max - iota) // 10
b // 9
c // 8
)
Go stdlib text scanner also uses this pattern.

Producing Alphabets
const (
// string will convert the
// expression into string.
//
// or, it'll assign character
// codes.
a = string(iota + 'a') // a
b // b
c // c
d // d
e // e
)

Bitwise operations
type Month int
const (
// 1 << 0 ==> 1
January Month = 1 << iota
February // 1 << 1 ==> 2
March // 1 << 2 ==> 4
April // 1 << 3 ==> 8
May // 1 << 4 ==> 16
June // ...
July
August
September
October
November
December
// Break the iota chain here.
// AllMonths will have only
// the assigned month values,
// not the iota's.
AllMonths = January | February |
March | April | May | June |
July | August | September |
October | November |
December
)
With the powers of 2, this code creates an all emcompassing constant from the previous constants.

Beware the zero-value
type Activity int
const (
Sleeping = iota
Walking
Running
)
func main() {
var activity Activity
// activity initialized to
// its zero-value of int
// which is Sleeping
}0 is a zero-value for integers. So, you can’t know whether the Activity is initialized or not; Is it really in the Sleeping state?

iota + 1 trick
const (
Sleeping = iota + 1
Walking
Running
)
func main() {
var activity Activity
// activity will be zero,
// so it's not initializedactivity = Sleeping
// now you know that it's been
// initialized
}
Use “iota + 1" to be sure that the enum type is initialized.

Unknown state pattern
const (
Unknown = iota
Sleeping
Walking
Running
)
Start with an “Unknown” to be sure of enum’s initialization.



▶︎ In Greek alphabet, iota is the ninth and the smallest letter (in terms of its visual representation). Pronounced like this. It represents a very small quantity of something.
⟦ In vector math, and in some programming languages, it’s been used to generate an array of consecutive integers as in 1, 2, 3, 4… ⟧
♛ If you’re curious just like me, you can read the implementation of constants, and iota in Go source code. Iota is declared here as const iota = 0. And, the constant implementation is here, and the behavior of incrementing iota is here.
★ Iota was in Iverson’s book: A Programming Language (APL) from 1962.
★ Iota borrowed from APL by one of the creators of Go, Ken Thompson.
★ A discussion to make iota work with variables in Go 2.


★ I’m also creating an online course for Go → Join to my newsletter
“ Let’s stay in touch weekly for new tutorials and tips “


I mostly tweet about Go tips and tricks — @inancgumus.


Don’t stop, learn more:
What the heck is all about typed and untyped constants? I’ve tried to craft an elegant visual guide for you.blog.learngoprogramming.com
Easily understand Golang variables with visual examples.blog.learngoprogramming.com
Also check out the other articles.


