Skip to Content
Go Realm v1 is released 🎉
TopicsEnum

Enums in Go

Go has no enum keyword. Instead, use this 3-step recipe:

1. Define a named type → type Status int 2. Declare constants → const ( Active Status = iota ... ) 3. Add String() method → func (s Status) String() string { ... }

1. iota — The Auto Counter

iota starts at 0 and increases by 1 for each line in a const block.

const ( A = iota // 0 ← iota starts here B // 1 ← iota auto-increments C // 2 )

iota resets to 0 at every new const keyword.


2. Building an Enum (Full Pattern)

// Step 1 — named type (prevents mixing with plain int) type Direction int // Step 2 — constants using iota const ( North Direction = iota // 0 East // 1 South // 2 West // 3 ) // Step 3 — String() so fmt.Println shows "North", not "0" func (d Direction) String() string { switch d { case North: return "North" case East: return "East" case South: return "South" case West: return "West" default: return fmt.Sprintf("Direction(%d)", d) } } fmt.Println(North) // "North" ← readable! fmt.Println(East) // "East"

3. Skip Zero — Avoid Silent Bugs ⭐

type Status int const ( _ Status = iota // skip 0 Active // 1 Inactive // 2 Banned // 3 )

Why? Go zero-initializes every variable. Without skipping 0, a freshly declared var s Status silently equals Active — a bug that’s hard to spot.

var s Status // = 0 fmt.Println(s == Active) // ❌ true! That's wrong — s was never set

4. Bit Flags with 1 << iota

Use when a value can hold multiple states at once (e.g. permissions).

type Permission int const ( Read Permission = 1 << iota // 1 → 001 Write // 2 → 010 Execute // 4 → 100 ) perm := Read | Write // combine: 3 → 011 fmt.Println(perm & Write != 0) // true — has write fmt.Println(perm & Execute != 0) // false — no execute
ConstantValueBinary
Read1001
Write2010
Execute4100
Read|Write3011

5. String Enums (for JSON / APIs)

type Environment string const ( Production Environment = "production" Staging Environment = "staging" Development Environment = "development" ) fmt.Println(Production) // "production" — no String() needed
Integer enumString enum
Auto-printable❌ needs String()✅ built-in
JSON outputnumber (1)string ("production")
Bit flags

6. iota Quick Reference

PatternExampleValues
From 0iota0, 1, 2…
Skip zero_ = iota then next1, 2, 3…
Bit flags1 << iota1, 2, 4, 8…
Offsetiota + 1010, 11, 12…

7. Common Mistakes ⚠️

MistakeProblemFix
0 is a valid stateuninitialized var silently matchesskip 0 with _ = iota
No String() methodlogs show 0, 1, 2add String() string
No default in switchunknown values silently ignoredalways add default
Using plain intno type safetyalways define a named type

8. Interview Cheat Sheet

Q: How do you define an enum in Go?

Named type + const block + iota. E.g. type Status int with const (Active Status = iota + 1 ...).

Q: What is iota?

An auto-incrementing counter (starts at 0) inside a const block. Resets at each new const.

Q: Why skip the zero value?

Go zero-initializes all variables. If 0 is a valid state, an unset variable silently looks valid — a hidden bug. Skipping makes uninitialized = invalid.

Q: How do you make an enum print nicely?

Implement String() string — this satisfies fmt.Stringer. fmt.Println calls it automatically.

Q: What is 1 << iota for?

Bit flags — each constant gets a unique power of 2, so multiple flags can be combined with | and checked with &.