Go Constants
Constants are identifiers whose values are determined at compile time and cannot be changed at runtime. Constants in Go provide a safe and efficient way to define immutable values. This chapter will detail constant declaration, types, special features, etc.
📋 Constant Basics
Constant Declaration
Basic Syntax
go
package main
import "fmt"
func main() {
// 1. Explicit type constants
const name string = "Go Language"
const version float64 = 1.21
const isStable bool = true
const maxUsers int = 1000
fmt.Printf("Language: %s\n", name)
fmt.Printf("Version: %.2f\n", version)
fmt.Printf("Stable: %t\n", isStable)
fmt.Printf("Max users: %d\n", maxUsers)
// 2. Type inference constants
const appName = "My App" // string
const port = 8080 // int
const timeout = 30.5 // float64
const debug = true // bool
fmt.Printf("App: %s, Port: %d\n", appName, port)
fmt.Printf("Timeout: %.1f seconds, Debug: %t\n", timeout, debug)
}Constant Characteristics
go
func main() {
const pi = 3.14159
// Constants are determined at compile time
fmt.Printf("π = %.5f\n", pi)
// Constants cannot be modified
// pi = 3.14 // Error! Constants cannot be reassigned
// Constant expressions are calculated at compile time
const (
radius = 5
area = pi * radius * radius // Calculated at compile time
circumference = 2 * pi * radius
)
fmt.Printf("Radius: %d\n", radius)
fmt.Printf("Area: %.2f\n", area)
fmt.Printf("Circumference: %.2f\n", circumference)
}Multi-Constant Declaration
Grouped Declaration
go
func main() {
// Use const() for grouped declaration
const (
// Application configuration
AppName = "User Management System"
AppVersion = "1.0.0"
AppAuthor = "Development Team"
// Server configuration
ServerHost = "localhost"
ServerPort = 8080
ServerSSL = false
// Database configuration
DBHost = "127.0.0.1"
DBPort = 3306
DBName = "userdb"
DBUser = "admin"
DBTimeout = 30
)
fmt.Printf("Application info: %s v%s by %s\n", AppName, AppVersion, AppAuthor)
fmt.Printf("Server: %s:%d (SSL: %t)\n", ServerHost, ServerPort, ServerSSL)
fmt.Printf("Database: %s:%d/%s (timeout: %ds)\n", DBHost, DBPort, DBName, DBTimeout)
}Declaration with Omitted Values
go
func main() {
const (
a = 1
b // b = 1 (inherits previous constant's value)
c // c = 1
d = 2
e // e = 2
f // f = 2
)
fmt.Printf("a=%d, b=%d, c=%d\n", a, b, c)
fmt.Printf("d=%d, e=%d, f=%d\n", d, e, f)
const (
red = "red"
green = "green"
blue = "blue"
yellow // yellow = "blue" (inherits previous value)
)
fmt.Printf("Colors: %s, %s, %s, %s\n", red, green, blue, yellow)
}🔢 iota Enumerator
Basic iota Usage
go
func main() {
// iota is a predeclared identifier for generating consecutive integer constants
const (
Monday = iota // 0
Tuesday // 1
Wednesday // 2
Thursday // 3
Friday // 4
Saturday // 5
Sunday // 6
)
fmt.Printf("Monday: %d\n", Monday)
fmt.Printf("Tuesday: %d\n", Tuesday)
fmt.Printf("Sunday: %d\n", Sunday)
// iota restarts in each const block
const (
January = iota + 1 // 1
February // 2
March // 3
)
fmt.Printf("January: %d, February: %d, March: %d\n", January, February, March)
}Advanced iota Usage
Skipping Values
go
func main() {
const (
Read = 1 << iota // 1 << 0 = 1
Write // 1 << 1 = 2
Execute // 1 << 2 = 4
)
fmt.Printf("Permissions - Read: %d, Write: %d, Execute: %d\n", Read, Write, Execute)
// Skip some values
const (
StatusOK = iota // 0
StatusWarning // 1
_ // 2 (skip)
StatusError // 3
StatusFatal // 4
)
fmt.Printf("Status codes - OK: %d, Warning: %d, Error: %d, Fatal: %d\n",
StatusOK, StatusWarning, StatusError, StatusFatal)
}Complex iota Expressions
go
func main() {
// Use iota for complex calculations
const (
_ = iota // 0 (skip)
KB = 1 << (10 * iota) // 1 << 10 = 1024
MB // 1 << 20 = 1048576
GB // 1 << 30 = 1073741824
TB // 1 << 40
)
fmt.Printf("Storage units:\n")
fmt.Printf("1 KB = %d bytes\n", KB)
fmt.Printf("1 MB = %d bytes\n", MB)
fmt.Printf("1 GB = %d bytes\n", GB)
fmt.Printf("1 TB = %d bytes\n", TB)
// Multiple iota expressions
const (
bit0, mask0 = 1 << iota, 1<<iota - 1 // 1, 0
bit1, mask1 // 2, 1
bit2, mask2 // 4, 3
bit3, mask3 // 8, 7
)
fmt.Printf("Bit operations:\n")
fmt.Printf("bit0=%d, mask0=%d\n", bit0, mask0)
fmt.Printf("bit1=%d, mask1=%d\n", bit1, mask1)
fmt.Printf("bit2=%d, mask2=%d\n", bit2, mask2)
fmt.Printf("bit3=%d, mask3=%d\n", bit3, mask3)
}🎭 Constant Types
Typed vs Untyped Constants
Typed Constants
go
func main() {
// Constants with explicitly specified types
const typedInt int = 42
const typedFloat float64 = 3.14
const typedString string = "Typed constant"
const typedBool bool = true
// Typed constants must exactly match variable types
var i int = typedInt // Correct
// var i32 int32 = typedInt // Error! Type mismatch
var i32 int32 = int32(typedInt) // Type conversion needed
fmt.Printf("Typed constants: %d, %g, %s, %t\n", typedInt, typedFloat, typedString, typedBool)
fmt.Printf("Converted int32: %d\n", i32)
}Untyped Constants
go
func main() {
// Untyped constants (literal constants)
const untypedInt = 42 // Untyped integer
const untypedFloat = 3.14 // Untyped floating-point
const untypedString = "Untyped" // Untyped string
// Untyped constants can be assigned to compatible types
var i int = untypedInt
var i32 int32 = untypedInt
var i64 int64 = untypedInt
var f32 float32 = untypedFloat
var f64 float64 = untypedFloat
fmt.Printf("Untyped integer assignment: int=%d, int32=%d, int64=%d\n", i, i32, i64)
fmt.Printf("Untyped float assignment: float32=%g, float64=%g\n", f32, f64)
// Untyped constant precision in operations
const huge = 1e1000 // Constant beyond any basic type range
fmt.Printf("Huge constant exists: %T\n", huge)
// Range check only at assignment time
// var x float64 = huge // Error! Exceeds float64 range
}Default Types of Constants
go
import "reflect"
func main() {
// Default types of untyped constants
const (
intConst = 42 // Default int
floatConst = 3.14 // Default float64
complexConst = 1 + 2i // Default complex128
runeConst = 'A' // Default rune (int32)
stringConst = "hello" // Default string
boolConst = true // Default bool
)
// Check variable types
var i = intConst
var f = floatConst
var c = complexConst
var r = runeConst
var s = stringConst
var b = boolConst
fmt.Printf("int constant type: %s\n", reflect.TypeOf(i))
fmt.Printf("float constant type: %s\n", reflect.TypeOf(f))
fmt.Printf("complex constant type: %s\n", reflect.TypeOf(c))
fmt.Printf("rune constant type: %s\n", reflect.TypeOf(r))
fmt.Printf("string constant type: %s\n", reflect.TypeOf(s))
fmt.Printf("bool constant type: %s\n", reflect.TypeOf(b))
}🔧 Constant Expressions
Compile-Time Calculation
go
import "math"
func main() {
// Constant expressions are calculated at compile time
const (
pi = 3.14159265358979323846
radius = 10
area = pi * radius * radius // Calculated at compile time
circumference = 2 * pi * radius // Calculated at compile time
)
fmt.Printf("π = %.15f\n", pi)
fmt.Printf("Radius = %d\n", radius)
fmt.Printf("Area = %.2f\n", area)
fmt.Printf("Circumference = %.2f\n", circumference)
// Operations that can be used
const (
a = 2 + 3 // Arithmetic operations
b = 10 / 3 // Integer division
c = 10.0 / 3.0 // Floating-point division
d = 2 << 3 // Bit operations
e = -5 // Unary operations
f = "hello" + "world" // String concatenation
)
fmt.Printf("Constant operations: a=%d, b=%d, c=%g, d=%d, e=%d, f=%s\n", a, b, c, d, e, f)
// Cannot use runtime functions
// const sqrt2 = math.Sqrt(2) // Error! math.Sqrt is a runtime function
}Type Conversion in Constants
go
func main() {
const (
// Type conversion can be done in constants
floatPi = 3.14159
intPi = int(floatPi) // Truncated to 3
stringNum = string(65) // Converted to character 'A'
runeNum = rune(65) // Converted to character 'A'
)
fmt.Printf("Original π: %g\n", floatPi)
fmt.Printf("Integer π: %d\n", intPi)
fmt.Printf("Character 65: %s\n", stringNum)
fmt.Printf("Rune65: %c\n", runeNum)
// Limitations of constant type conversion
const bigInt = 1000000000000000000
// const overflow = int32(bigInt) // Error! Overflow detected at compile time
const validInt32 = int32(1000) // Correct, within range
fmt.Printf("Valid int32 constant: %d\n", validInt32)
}🎯 Practical Application Examples
Configuration Constants
go
package main
import "fmt"
// Application configuration constants
const (
// Application info
AppName = "E-commerce System"
AppVersion = "2.1.0"
AppAuthor = "Development Team"
// Server configuration
DefaultHost = "0.0.0.0"
DefaultPort = 8080
DefaultTimeout = 30
// Database configuration
MaxConnections = 100
ConnectionTimeout = 5
QueryTimeout = 30
// Business rules
MaxOrderItems = 50
MaxUserSessions = 5
SessionTimeout = 3600 // seconds
CacheExpiration = 1800 // seconds
)
func main() {
fmt.Printf("=== %s v%s ===\n", AppName, AppVersion)
fmt.Printf("Development team: %s\n", AppAuthor)
fmt.Printf("\nServer configuration:\n")
fmt.Printf(" Address: %s:%d\n", DefaultHost, DefaultPort)
fmt.Printf(" Timeout: %d seconds\n", DefaultTimeout)
fmt.Printf("\nDatabase configuration:\n")
fmt.Printf(" Max connections: %d\n", MaxConnections)
fmt.Printf(" Connection timeout: %d seconds\n", ConnectionTimeout)
fmt.Printf(" Query timeout: %d seconds\n", QueryTimeout)
fmt.Printf("\nBusiness rules:\n")
fmt.Printf(" Max items per order: %d\n", MaxOrderItems)
fmt.Printf(" Max sessions per user: %d\n", MaxUserSessions)
fmt.Printf(" Session timeout: %d seconds\n", SessionTimeout)
}Enumeration Constants
go
// Order status enumeration
const (
OrderPending = iota // 0 - Pending
OrderConfirmed // 1 - Confirmed
OrderPaid // 2 - Paid
OrderShipped // 3 - Shipped
OrderDelivered // 4 - Delivered
OrderCancelled // 5 - Cancelled
OrderRefunded // 6 - Refunded
)
// User permission bit flags
const (
PermissionRead = 1 << iota // 1 - Read permission
PermissionWrite // 2 - Write permission
PermissionDelete // 4 - Delete permission
PermissionAdmin // 8 - Admin permission
)
// Error codes
const (
ErrCodeSuccess = 0
ErrCodeInvalidParam = 1001
ErrCodeUserNotFound = 1002
ErrCodePasswordWrong = 1003
ErrCodePermissionDenied = 1004
ErrCodeSystemError = 5000
)
func main() {
// Use order status
currentStatus := OrderPaid
fmt.Printf("Current order status: %d\n", currentStatus)
// Use permission bit flags
userPermissions := PermissionRead | PermissionWrite // 3
hasReadPermission := userPermissions&PermissionRead != 0
hasDeletePermission := userPermissions&PermissionDelete != 0
fmt.Printf("User permissions: %d\n", userPermissions)
fmt.Printf("Has read permission: %t\n", hasReadPermission)
fmt.Printf("Has delete permission: %t\n", hasDeletePermission)
// Use error codes
errorCode := ErrCodeUserNotFound
errorMessage := getErrorMessage(errorCode)
fmt.Printf("Error code: %d, Error message: %s\n", errorCode, errorMessage)
}
func getErrorMessage(code int) string {
switch code {
case ErrCodeSuccess:
return "Success"
case ErrCodeInvalidParam:
return "Invalid parameter"
case ErrCodeUserNotFound:
return "User not found"
case ErrCodePasswordWrong:
return "Wrong password"
case ErrCodePermissionDenied:
return "Permission denied"
case ErrCodeSystemError:
return "System error"
default:
return "Unknown error"
}
}Math and Physics Constants
go
import "math"
// Math constants
const (
Pi = 3.14159265358979323846
E = 2.71828182845904523536
Phi = 1.61803398874989484820 // Golden ratio
)
// Physics constants
const (
SpeedOfLight = 299792458 // Speed of light (m/s)
GravityEarth = 9.80665 // Earth gravity acceleration (m/s²)
AvogadroNumber = 6.02214076e23 // Avogadro constant
PlanckConstant = 6.62607015e-34 // Planck constant (J⋅s)
)
// Unit conversion constants
const (
// Length units (convert to meters)
Millimeter = 0.001
Centimeter = 0.01
Meter = 1.0
Kilometer = 1000.0
// Time units (convert to seconds)
Nanosecond = 1e-9
Microsecond = 1e-6
Millisecond = 1e-3
Second = 1.0
Minute = 60.0
Hour = 3600.0
Day = 86400.0
)
func main() {
// Use math constants
radius := 5.0
area := Pi * radius * radius
circumference := 2 * Pi * radius
fmt.Printf("Circle calculation (radius=%.1f):\n", radius)
fmt.Printf(" Area: %.2f\n", area)
fmt.Printf(" Circumference: %.2f\n", circumference)
// Use physics constants
distance := 1.0 * Kilometer // 1 kilometer
time := distance / SpeedOfLight
fmt.Printf("\nLight propagation calculation:\n")
fmt.Printf(" Distance: %.0f meters\n", distance)
fmt.Printf(" Light propagation time: %.2e seconds\n", time)
// Unit conversion
lengthInCm := 150.0 // 150 centimeters
lengthInM := lengthInCm * Centimeter
timeInMs := 500.0 // 500 milliseconds
timeInS := timeInMs * Millisecond
fmt.Printf("\nUnit conversion:\n")
fmt.Printf(" %.0f centimeters = %.2f meters\n", lengthInCm, lengthInM)
fmt.Printf(" %.0f milliseconds = %.3f seconds\n", timeInMs, timeInS)
}🎓 Summary
In this chapter, we deeply learned about Go constants:
- ✅ Constant Declaration: const keyword, type inference, grouped declaration
- ✅ iota Enumerator: auto-increment, complex expressions, bit flags
- ✅ Constant Types: typed vs untyped constants, default types
- ✅ Constant Expressions: compile-time calculation, type conversion
- ✅ Practical Applications: configuration constants, enumerations, math/physics constants
Constants are an important feature in Go. Using constants correctly can make code safer, more efficient, and easier to maintain.
Next, we will learn Go Operators to master the usage of various operators.
Constant Usage Suggestions
- Use constants to define configuration values and magic numbers
- Use iota to create enumerations and bit flags
- Prefer untyped constants for better flexibility
- Use descriptive names for constants
- Organize related constants together