Constants in Go
const keyword, iota, and typed constants
The const Keyword
Go has first-class support for constants through the const keyword. Constants in Go must be expressible as compile-time values — they can be numbers, strings, booleans, or expressions composed of other constants. Unlike variables, constants in Go have no memory address and cannot be referenced with a pointer.
const MaxRetries = 3
const DefaultTimeout = 30 * time.Second
const APIBaseURL = "https://api.example.com/v1"
// Grouped constants
const (
StatusOK = 200
StatusNotFound = 404
StatusError = 500
)Go constants can be typed or untyped. An untyped constant has a "kind" rather than a fixed type, which gives it higher precision and more flexible use. The constant 3.14159 can be used wherever a float32, float64, or even a user-defined float type is expected. A typed constant is restricted to its declared type.
// Untyped constant — can be used as float32, float64, etc.
const Pi = 3.14159265358979323846
// Typed constant — restricted to float64
const TypedPi float64 = 3.14159265358979323846
var f32 float32 = Pi // OK: untyped constant adapts
// var f32 float32 = TypedPi // Error: cannot use float64 as float32iota: The Constant Generator
Go's iota is a powerful tool for generating sequences of related constants. It starts at 0 in each const block and increments by 1 for each constant specification. Combined with expressions, iota can generate bitmasks, powers of two, offsets, and other patterns.
// Simple enumeration
type Weekday int
const (
Sunday Weekday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
// Bitmask flags
type Permission uint
const (
Read Permission = 1 << iota // 1
Write // 2
Execute // 4
)
// Byte size units
const (
_ = iota // skip 0
KB = 1 << (10 * iota) // 1024
MB // 1048576
GB // 1073741824
TB // 1099511627776
)The blank identifier _ can skip values in an iota sequence. This is commonly used to skip 0 so that the zero value of the type is distinct from any named constant, which helps catch uninitialized variables.
Typed Constants and Enumerations
Go does not have a dedicated enum type, but the idiomatic pattern is to define a named type and a set of typed constants using iota. This gives you type safety — you cannot accidentally pass an untyped integer where a Weekday is expected (though the type system allows explicit conversion).
type Direction int
const (
North Direction = iota
East
South
West
)
// String method for readable output
func (d Direction) String() string {
names := [...]string{"North", "East", "South", "West"}
if d < North || d > West {
return "Unknown"
}
return names[d]
}
func move(d Direction) {
fmt.Println("Moving", d)
}
move(North) // "Moving North"
// move(42) // Cannot use 42 (untyped int) as DirectionBuilt-in Constants
Go has only three predeclared constants: true, false, and iota. The standard library provides additional constants in packages like math, os, and unicode:
import "math"
math.Pi // 3.141592653589793
math.E // 2.718281828459045
math.Phi // 1.618033988749895 (golden ratio)
math.Ln2 // 0.6931471805599453
math.Ln10 // 2.302585092994046
math.MaxFloat64 // ~1.8e308
math.MaxInt64 // 9223372036854775807
math.MinInt64 // -9223372036854775808Common Patterns
- Group related constants in a
const ( ... )block. Use separate blocks for unrelated groups. - Exported constants start with an uppercase letter. Unexported constants start with lowercase and are scoped to the package.
- Use
iotafor sequential enumerations but be cautious about adding values in the middle — it shifts all subsequent values and can break serialized data. - Skip the zero value with
_ = iotaso the zero value of the type signals "uninitialized" rather than accidentally matching a valid constant. - Use the
go generatetool withstringerto automatically generateString()methods for constant types.