Constants and iota
Some values never change. The speed of light, the name of your application, the maximum number of retries before giving up: once these are set, they stay set for the life of the program. In Go, a constant is how you declare such a value, and the compiler enforces that it never changes.
You declare a constant with const:
const Greeting = "Hello"
Constants can hold strings, whole numbers, decimal numbers (what Go calls floats, covered properly in a later lesson), or booleans. They cannot hold values that need to be computed at runtime, such as the result of reading a file or the current time.
const versus var
const works at the top level of a file, just like var, and also inside functions. The crucial difference is that the value of a constant must be known to the compiler before the program runs:
const MaxUsers = 100 // fine, a fixed number
const Pi = 3.14159 // fine, a decimal literal
var count = 42
const Copy = count // error, count is a variable (a runtime value), not a constant
Anything that would require running code to produce its value (reading a file, measuring time, calling a function that does real work) is not allowed in a const. In return for this restriction, constants can be used anywhere Go requires a compile-time value, and the compiler can often inline them by replacing uses with the literal value.
Typed versus untyped constants
Most constants you write are untyped. const Pi = 3.14159 does not have a fixed type; Go gives it one later, based on where it is used:
const Pi = 3.14159
var small float32 = Pi // Pi is treated as float32 here
var big float64 = Pi // same Pi, treated as float64 here
You can pin a type explicitly if you want:
const MaxUsers int = 100
var bad float64 = MaxUsers // error: cannot use MaxUsers (int) as float64
var good float64 = float64(MaxUsers) // fine, with an explicit conversion
Once MaxUsers has a fixed type, every use has to match that type or use an explicit conversion.
Leave your constants untyped (no explicit type) unless a specific API forces one. An untyped constant adapts to whatever numeric context it ends up in, so the same const Pi = 3.14159 works as a float32 in one call and a float64 in another, with no conversions or duplicates.
Grouped declarations
When you have several related constants, group them in a parenthesised block:
const (
StatusPending = "pending"
StatusActive = "active"
StatusArchived = "archived"
)
This is purely a syntactic convenience. It keeps related constants together and saves you from writing const on every line.
iota for numbered constants
Inside a grouped const block, the identifier iota is a counter that starts at 0 on the first line and increments by one on each subsequent line:
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
)
Each line after the first reuses the expression from the line above (which is iota), so you do not need to write it again. By the time the block ends, you have a tidy set of numbered constants with no magic numbers or hand-counted integers. This is Go's idiom for enumerations.
iota can also be used for bit flags, skipped values, and custom numbering schemes. Those patterns are covered in the Idioms chapter.
Use a grouped const block with iota to define four seasons in this order: Spring, Summer, Autumn, Winter. Print them all on one line with fmt.Println so you can see the values the compiler assigned.
0 1 2 3