Constants and iota are how Go expresses fixed values and enum-like sets.
A constant is a value fixed at compile time: const Pi = 3.14159. Constants can be numbers, strings, booleans or runes — not slices, maps or structs.
Most constants are untyped. const Big = 1 << 40 has no fixed type; it takes on whatever type the context needs, and arithmetic on untyped constants is done with arbitrary precision. That's why const Timeout = 5 can be used as an int in one place and a float64 in another, and why time.Second * 5 works without a conversion. A typed constant, const Max int32 = 100, behaves like a value of that type.
Go has no enum keyword. Instead, inside a const ( ... ) block, iota starts at 0 and increments on each line. A line with no expression repeats the previous expression with the new iota:
KB = 1 << (10 * (iota + 1))on the first line, then justMB,GBon the following lines, yields 1024, 1048576, …- Use
_ = iotato skip a value, for example to keep the zero value as "unknown".
The idiomatic enum is a named integer type plus constants of that type. Adding a String() string method makes values print nicely (the stringer tool can generate it). Enums are not closed: any Weekday(42) is a legal value, so validate input from outside.
Example
package main
import "fmt"
type Level int
const (
Debug Level = iota // 0
Info // 1
Warn // 2
Error // 3
)
func (l Level) String() string {
return [...]string{"DEBUG", "INFO", "WARN", "ERROR"}[l]
}
const timeout = 5 // untyped: usable as int or float64
func main() {
fmt.Println(Warn, int(Warn)) // WARN 2
var f float64 = timeout / 2.0 // 2.5
fmt.Println(f)
}Remember
- Untyped constants adapt to context and are exact at compile time
iotacounts lines in a const block — Go's enum idiom- Give enum types a String() method for readable output
Watch out for
- Assuming Go enums are closed — any integer can be converted to the type.