Constants in Go
Constants are immutable, compile-time values. They improve clarity, safety, and performance. By default, constants are untyped and adapt to context.
Core ideas
- Immutable: cannot change after declaration
- Compile-time: evaluated by the compiler when possible
- Untyped by default: adapt to assignment context
Basic and untyped constants
package main
import "fmt"
func main() {
const msg = "Hello" // untyped string
const n = 42 // untyped number
const r = 0.15 // untyped float
const on = true // untyped bool
var i int = n // ok: n adapts to int
var f64 = r * 2.0 // ok: r adapts to float64
fmt.Println(msg, i, f64, on)
}
Notes:
- Untyped constants don’t overflow until given a type; they can represent arbitrarily large precision within spec limits
Groups
Group related constants to improve readability. Parentheses open a constant declaration block.
const (
AppName = "GistDev"
AppVersion = "1.0.0"
Port = 8080
Debug = true
)
iota (auto-increment)
iota increments automatically within a constant block, letting you define sequences concisely (enums, bit sizes, flags).
package main
import "fmt"
func main() {
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
)
const (
KB = 1 << (10 * iota) // 1, 1024, 1048576, ...
MB
GB
)
fmt.Println(Sunday, Monday, Tuesday)
fmt.Println(KB, MB, GB)
}
Tips:
- You can skip values with
_and compute from previous ones
Typed constants and enum-like patterns
package main
import "fmt"
type Status int
const (
StatusPending Status = iota
StatusRunning
StatusDone
)
func (s Status) String() string {
switch s {
case StatusPending:
return "Pending"
case StatusRunning:
return "Running"
case StatusDone:
return "Done"
default:
return "Unknown"
}
}
func main() {
s := StatusRunning
fmt.Println(s, s.String())
}
Use typed constants to create safe, expressive APIs and avoid mixing unrelated values.
Constants vs variables
- Constants: compile-time facts (timeouts, sizes, names)
- Variables: runtime values (timestamps, counters, flags)
package main
import (
"fmt"
"time"
)
const (
DefaultTimeout = 30 * time.Second
MaxRetries = 3
)
var (
start = time.Now()
connected bool
)
func main() {
fmt.Println(DefaultTimeout, MaxRetries, start.IsZero(), connected)
}
Best practices
- Prefer untyped consts for flexibility; use typed when you need strictness
- Group related constants in const blocks; name clearly
- Use iota for sequences; skip with
_if needed - Avoid magic numbers; replace with named constants
- Document units (e.g., durations, sizes) in constant names or comments
Summary
- Constants are compile-time, immutable values
iotahelps define sequences succinctly- Typed constants enable safe, enum-like APIs
- Use constants to make code clearer and cheaper at runtime