Skip to content

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

Content is for learning and research only.