Go Constants
A constant holds a value that cannot change after it is declared. Where a variable is a container you can update as your program runs, a constant is a fixed, named value — useful for things like configuration limits, mathematical values, or settings that should never be accidentally reassigned.
Constants are declared with the const keyword.
Syntax
const name type = value
name— the constant's identifier, following the same naming rules as variables.type— optional; Go can infer it from the value.value— must be provided at declaration. Unlikevar, a constant can never be declared without a value and filled in later.
package main
import "fmt"
const MaxUsers = 100
func main() {
fmt.Println("Maximum allowed users:", MaxUsers)
}
Key Rules for Constants
- Must be assigned a value at the point of declaration.
- Cannot be reassigned afterward — attempting
MaxUsers = 200later in the program is a compile error, not a runtime one, so the mistake is caught immediately. - Can be declared inside a function or at package level.
- A constant's value must be computable at compile time — you can use a constant expression like
60 * 60, but not the result of a function call liketime.Now(). - Common Go style capitalizes the first letter of a constant when it should be exported (visible outside the package), following the same capitalization rule used for exported variables and functions — not because it is a constant, but because of Go's general visibility rule.
Typed vs. Untyped Constants
Go has a feature that surprises many newcomers: constants can be untyped, carrying no fixed type until they are actually used in an expression. This is different from variables, which always have a concrete type from the moment they exist.
Typed Constants
A typed constant behaves like an immutable variable of that exact type:
package main
import "fmt"
const TimeoutSeconds int = 30
func main() {
fmt.Println("Timeout:", TimeoutSeconds)
}
Use a typed constant when you need strict type checking — for example, when passing it to a function that requires a specific parameter type.
Untyped Constants
An untyped constant has no fixed type of its own; Go assigns it a type based on the context where it's used, at compile time:
package main
import "fmt"
const Discount = 0.15
func main() {
finalPrice := 200 * (1 - Discount)
fmt.Println("Final price:", finalPrice)
}
Here, Discount has no fixed type. When it's used in 200 * (1 - Discount), Go treats it as a float64 because that's what the surrounding arithmetic requires. This flexibility is why untyped numeric constants can be freely mixed with int, float64, or other numeric types without an explicit conversion — something a typed variable could never do.
Advantages of untyped constants:
- They adapt automatically to whatever numeric type an expression needs.
- They avoid the type-mismatch errors you'd get mixing, say, an
intvariable with afloat64variable directly.
Grouping Constants
Related constants can be declared together in a block, which keeps configuration values organized and easy to scan:
package main
import "fmt"
const (
AppName = "ShopEasy"
Version = "1.0.0"
MaxRetries = 3
)
func main() {
fmt.Println(AppName, "Version:", Version)
fmt.Println("Max retries:", MaxRetries)
}
Expected output:
ShopEasy Version: 1.0.0
Max retries: 3
Common mistake: trying to use := with constants. Short declaration only works for variables — constants must always use const, and always need =, not :=.