Skip to content

Go Variables

Variables are containers for storing data in programs. Go provides multiple ways to declare and initialize variables. This chapter will detail variable declaration, initialization, scope, and other core concepts in Go.

📋 Variable Declaration

Basic Declaration Syntax

var Keyword Declaration

go
package main

import "fmt"

func main() {
    // 1. Declare variables without initialization (use zero values)
    var name string
    var age int
    var height float64
    var isStudent bool
    
    fmt.Printf("Name: %q\n", name)        // ""
    fmt.Printf("Age: %d\n", age)         // 0
    fmt.Printf("Height: %g\n", height)      // 0
    fmt.Printf("Is student: %t\n", isStudent) // false
    
    // 2. Declare with type and initial value
    var userName string = "Zhang San"
    var userAge int = 25
    var userHeight float64 = 1.75
    var userIsStudent bool = true
    
    fmt.Printf("User name: %s\n", userName)
    fmt.Printf("User age: %d\n", userAge)
    fmt.Printf("User height: %.2f\n", userHeight)
    fmt.Printf("Is student: %t\n", userIsStudent)
}

Type Inference

go
func main() {
    // 3. Omit type, let compiler infer
    var name = "Li Si"        // inferred as string
    var age = 30            // inferred as int
    var salary = 5000.50    // inferred as float64
    var married = false     // inferred as bool
    
    fmt.Printf("Name: %s (type: %T)\n", name, name)
    fmt.Printf("Age: %d (type: %T)\n", age, age)
    fmt.Printf("Salary: %.2f (type: %T)\n", salary, salary)
    fmt.Printf("Married: %t (type: %T)\n", married, married)
}

Multi-Variable Declaration

Same-Type Multi-Variable Declaration

go
func main() {
    // 1. Declare multiple variables of the same type simultaneously
    var x, y, z int
    fmt.Printf("x: %d, y: %d, z: %d\n", x, y, z)  // 0, 0, 0
    
    // 2. Declare and initialize simultaneously
    var a, b, c int = 1, 2, 3
    fmt.Printf("a: %d, b: %d, c: %d\n", a, b, c)  // 1, 2, 3
    
    // 3. Multi-variable declaration with type inference
    var name, city = "Wang Wu", "Beijing"
    var count, price = 10, 99.99
    fmt.Printf("Name: %s, City: %s\n", name, city)
    fmt.Printf("Count: %d, Price: %.2f\n", count, price)
}

Different-Type Multi-Variable Declaration

go
func main() {
    // Use type inference to declare variables of different types
    var (
        name    = "Zhao Liu"
        age     = 28
        height  = 1.80
        married = true
    )
    
    fmt.Printf("Personal information:\n")
    fmt.Printf("  Name: %s\n", name)
    fmt.Printf("  Age: %d\n", age)
    fmt.Printf("  Height: %.2f\n", height)
    fmt.Printf("  Married: %t\n", married)
}

Variable Group Declaration

go
func main() {
    // Use var() for grouped declaration
    var (
        // Server configuration
        serverHost string = "localhost"
        serverPort int    = 8080
        serverSSL  bool   = false
        
        // Database configuration
        dbHost     = "127.0.0.1"  // string
        dbPort     = 3306         // int
        dbName     = "testdb"     // string
        dbUser     = "root"       // string
        dbPassword = "password"   // string
    )
    
    fmt.Printf("Server configuration: %s:%d, SSL: %t\n", serverHost, serverPort, serverSSL)
    fmt.Printf("Database configuration: %s:%d/%s, User: %s\n", dbHost, dbPort, dbName, dbUser)
}

⚡ Short Variable Declaration

Basic Usage

go
func main() {
    // Short variable declaration := (can only be used inside functions)
    name := "Short variable"
    age := 20
    price := 19.99
    active := true
    
    fmt.Printf("Name: %s\n", name)
    fmt.Printf("Age: %d\n", age)
    fmt.Printf("Price: %.2f\n", price)
    fmt.Printf("Active: %t\n", active)
    
    // Multi-variable short declaration
    x, y, z := 1, 2, 3
    fmt.Printf("Coordinates: (%d, %d, %d)\n", x, y, z)
    
    // Mixed-type short declaration
    username, userid, score := "admin", 1001, 95.5
    fmt.Printf("User: %s, ID: %d, Score: %.1f\n", username, userid, score)
}

Redeclaration with Short Variable Declaration

go
func main() {
    // Special rules for short variable declaration: redeclaration
    name := "Original name"
    fmt.Printf("Initial name: %s\n", name)
    
    // If there are new variables on the left, can redeclare existing variables
    name, age := "New name", 25  // name is reassigned, age is newly declared
    fmt.Printf("Updated: Name %s, Age %d\n", name, age)
    
    // But there must be at least one new variable
    // name, age := "Another name", 30  // Error! No new variable
    
    // This is correct
    name, age, city := "Final name", 30, "Shanghai"  // city is new variable
    fmt.Printf("Final: Name %s, Age %d, City %s\n", name, age, city)
}

🎯 Variable Scope

Package-Level Variables

go
package main

import "fmt"

// Package-level variables (global variables)
var globalVar = "Global variable"
var (
    appName    = "My App"
    appVersion = "1.0.0"
    appAuthor  = "Developer"
)

func main() {
    fmt.Printf("Global variable: %s\n", globalVar)
    fmt.Printf("Application info: %s v%s by %s\n", appName, appVersion, appAuthor)
    
    // Functions can access global variables
    showGlobalVar()
    
    // Local variables
    localVar := "Local variable"
    fmt.Printf("Local variable: %s\n", localVar)
    
    // Block scope
    {
        blockVar := "Block variable"
        fmt.Printf("Inside block: %s\n", blockVar)
        fmt.Printf("Inside block accessing local variable: %s\n", localVar)
        fmt.Printf("Inside block accessing global variable: %s\n", globalVar)
    }
    // fmt.Printf("Outside block: %s\n", blockVar)  // Error! Out of scope
}

func showGlobalVar() {
    fmt.Printf("Global variable in function: %s\n", globalVar)
}

Variable Shadowing

go
var x = "Global x"

func main() {
    fmt.Printf("Global x: %s\n", x)
    
    // Local variable shadows global variable
    x := "Local x"
    fmt.Printf("Local x: %s\n", x)
    
    {
        // Block variable shadows local variable
        x := "Block x"
        fmt.Printf("Block x: %s\n", x)
        
        {
            // Deeper shadowing
            x := "Inner block x"
            fmt.Printf("Inner block x: %s\n", x)
        }
        
        fmt.Printf("Back to block x: %s\n", x)
    }
    
    fmt.Printf("Back to local x: %s\n", x)
    
    // Access global variable (if needed)
    showGlobal()
}

func showGlobal() {
    fmt.Printf("Access global x in function: %s\n", x)
}

💡 Variable Initialization

Zero-Value Initialization

go
func main() {
    // All variables in Go are initialized to zero values
    var intVar int
    var floatVar float64
    var boolVar bool
    var stringVar string
    var pointerVar *int
    var sliceVar []int
    var mapVar map[string]int
    var chanVar chan int
    var funcVar func()
    
    fmt.Printf("int zero value: %d\n", intVar)
    fmt.Printf("float64 zero value: %g\n", floatVar)
    fmt.Printf("bool zero value: %t\n", boolVar)
    fmt.Printf("string zero value: %q\n", stringVar)
    fmt.Printf("pointer zero value: %v\n", pointerVar)
    fmt.Printf("slice zero value: %v\n", sliceVar)
    fmt.Printf("map zero value: %v\n", mapVar)
    fmt.Printf("chan zero value: %v\n", chanVar)
    fmt.Printf("func zero value: %v\n", funcVar)
}

Explicit Initialization

go
func main() {
    // Initialize during declaration
    var name string = "Initial value"
    var count int = 100
    var rate float64 = 0.95
    var enabled bool = true
    
    fmt.Printf("Initialized variables:\n")
    fmt.Printf("  name: %s\n", name)
    fmt.Printf("  count: %d\n", count)
    fmt.Printf("  rate: %.2f\n", rate)
    fmt.Printf("  enabled: %t\n", enabled)
    
    // Subsequent assignment
    name = "Modified value"
    count = 200
    rate = 0.85
    enabled = false
    
    fmt.Printf("Modified variables:\n")
    fmt.Printf("  name: %s\n", name)
    fmt.Printf("  count: %d\n", count)
    fmt.Printf("  rate: %.2f\n", rate)
    fmt.Printf("  enabled: %t\n", enabled)
}

🔄 Variable Assignment

Basic Assignment

go
func main() {
    // Declare first, then assign
    var name string
    name = "Assignment example"
    
    var age int
    age = 25
    
    fmt.Printf("Name: %s, Age: %d\n", name, age)
    
    // Reassignment
    name = "New name"
    age = 30
    
    fmt.Printf("Updated: Name: %s, Age: %d\n", name, age)
}

Multiple Assignment

go
func main() {
    // Multiple assignment (parallel assignment)
    var a, b, c int
    
    a, b, c = 1, 2, 3
    fmt.Printf("a: %d, b: %d, c: %d\n", a, b, c)
    
    // Swap variable values
    a, b = b, a
    fmt.Printf("After swap a: %d, b: %d\n", a, b)
    
    // Assignment of function return values
    name, age := getPersonInfo()
    fmt.Printf("Personal info: %s, %d years old\n", name, age)
    
    // Ignore some return values
    name2, _ := getPersonInfo()  // Ignore age
    fmt.Printf("Name only: %s\n", name2)
}

func getPersonInfo() (string, int) {
    return "Zhang San", 28
}

Increment and Decrement

go
func main() {
    // Increment/decrement operators
    var counter int = 10
    
    fmt.Printf("Initial value: %d\n", counter)
    
    counter++  // Increment
    fmt.Printf("After increment: %d\n", counter)
    
    counter--  // Decrement
    fmt.Printf("After decrement: %d\n", counter)
    
    // Note: Go has no pre-increment/decrement
    // ++counter  // Error
    // --counter  // Error
    
    // Cannot be used as expression
    // var x = counter++  // Error
    
    // Can only be used as statement
    counter++
    var x = counter  // Correct
    fmt.Printf("x: %d\n", x)
}

🌍 Variable Lifecycle

Local Variable Lifecycle

go
func main() {
    fmt.Println("main function starts")
    
    {
        fmt.Println("Entering block")
        localVar := "Local variable"
        fmt.Printf("Created local variable: %s\n", localVar)
        
        processVar(localVar)
        
        // localVar is destroyed when block ends
        fmt.Println("About to leave block")
    }
    
    // fmt.Println(localVar)  // Error! Variable no longer exists
    fmt.Println("main function ends")
}

func processVar(data string) {
    fmt.Printf("Processing variable: %s\n", data)
    tempVar := "Temporary variable"
    fmt.Printf("Temporary variable: %s\n", tempVar)
    // tempVar is destroyed when function ends
}

Variable Escape Analysis

go
// Variables may escape to heap in these cases
func createPointer() *int {
    localVar := 42
    return &localVar  // localVar escapes to heap
}

func main() {
    // Local variable, on stack
    stackVar := 100
    fmt.Printf("Stack variable: %d\n", stackVar)
    
    // Escaped variable, on heap
    heapVar := createPointer()
    fmt.Printf("Heap variable: %d\n", *heapVar)
}

🎯 Variable Naming Conventions

Naming Styles

go
package main

import "fmt"

// Exported variables (capitalized)
var PublicVariable = "Public variable"

// Package-level variables (lowercase)
var privateVariable = "Private variable"

func main() {
    // 1. Use camel case
    var userName string = "User name"
    var userAge int = 25
    var isUserActive bool = true
    
    // 2. Common abbreviations remain capitalized
    var httpURL string = "http://example.com"
    var jsonData string = `{"name": "test"}`
    var xmlContent string = "<root></root>"
    
    // 3. Use short names for short scope
    for i := 0; i < 5; i++ {
        fmt.Printf("Index: %d\n", i)
    }
    
    // 4. Boolean variables use is/has/can prefixes
    var isReady bool = true
    var hasPermission bool = false
    var canEdit bool = true
    
    // 5. Avoid meaningless names
    // Bad naming
    // var data string
    // var info int
    // var temp bool
    
    // Good naming
    var customerName string = "Customer name"
    var orderCount int = 10
    var paymentReceived bool = true
    
    fmt.Printf("User info: %s, %d years old, active: %t\n", userName, userAge, isUserActive)
    fmt.Printf("Status: ready=%t, permission=%t, editable=%t\n", isReady, hasPermission, canEdit)
    fmt.Printf("Business info: %s, order count=%d, paid=%t\n", customerName, orderCount, paymentReceived)
}

Variable Naming Best Practices

go
func main() {
    // ✅ Good naming examples
    var (
        // Clearly express purpose
        maxRetryCount    = 3
        connectionTimeout = 30
        serverAddress    = "localhost:8080"
        
        // Boolean variables have clear meaning
        isConnected     = false
        hasErrors       = false
        canRetry        = true
        shouldLog       = true
        
        // Collections use plural form
        userNames       = []string{"Zhang San", "Li Si"}
        errorMessages   = []string{}
        configSettings  = map[string]string{}
        
        // Counters and indices
        userCount       = len(userNames)
        currentIndex    = 0
        totalProcessed  = 0
    )
    
    // ❌ Naming to avoid
    // var d string          // Too short, meaningless
    // var temp int          // Too generic
    // var data interface{}  // Too abstract
    // var mgr *Manager      // Abbreviation unclear
    
    fmt.Printf("Server: %s, Timeout: %d seconds\n", serverAddress, connectionTimeout)
    fmt.Printf("User count: %d, Current index: %d\n", userCount, currentIndex)
    fmt.Printf("Connection status: %t, Retryable: %t\n", isConnected, canRetry)
}

🎯 Practical Example

User Information Management System

go
package main

import (
    "fmt"
    "time"
)

// Global configuration variables
var (
    systemName    = "User Management System"
    systemVersion = "1.0.0"
    maxUsers      = 1000
)

func main() {
    fmt.Printf("=== %s v%s ===\n", systemName, systemVersion)
    
    // User information variables
    var (
        userID       int
        userName     string
        userEmail    string
        userAge      int
        isActive     bool
        lastLoginTime time.Time
    )
    
    // Initialize user information
    userID = 1001
    userName = "Zhang San"
    userEmail = "zhangsan@example.com"
    userAge = 28
    isActive = true
    lastLoginTime = time.Now()
    
    // Display user information
    displayUserInfo(userID, userName, userEmail, userAge, isActive, lastLoginTime)
    
    // Batch create users
    users := createMultipleUsers()
    fmt.Printf("\nCreated %d users:\n", len(users))
    for i, user := range users {
        fmt.Printf("%d. %s\n", i+1, user)
    }
    
    // System statistics
    var (
        totalUsers    = len(users) + 1  // Include first user
        activeUsers   = 0
        inactiveUsers = 0
    )
    
    // Simple statistics (example)
    if isActive {
        activeUsers++
    } else {
        inactiveUsers++
    }
    activeUsers += len(users)  // Assume batch created are all active users
    
    fmt.Printf("\n=== System Statistics ===\n")
    fmt.Printf("Total users: %d\n", totalUsers)
    fmt.Printf("Active users: %d\n", activeUsers)
    fmt.Printf("Inactive users: %d\n", inactiveUsers)
    fmt.Printf("System capacity: %d (remaining: %d)\n", maxUsers, maxUsers-totalUsers)
}

func displayUserInfo(id int, name, email string, age int, active bool, lastLogin time.Time) {
    fmt.Printf("\n=== User Information ===\n")
    fmt.Printf("ID: %d\n", id)
    fmt.Printf("Name: %s\n", name)
    fmt.Printf("Email: %s\n", email)
    fmt.Printf("Age: %d\n", age)
    fmt.Printf("Status: %s\n", getActiveStatus(active))
    fmt.Printf("Last login: %s\n", lastLogin.Format("2006-01-02 15:04:05"))
}

func getActiveStatus(active bool) string {
    if active {
        return "Active"
    }
    return "Inactive"
}

func createMultipleUsers() []string {
    // Use short variable declaration to create user list
    users := []string{}
    
    // Batch add users
    userNames := []string{"Li Si", "Wang Wu", "Zhao Liu", "Sun Qi"}
    
    for _, name := range userNames {
        userInfo := fmt.Sprintf("%s (ID: %d)", name, 1000+len(users)+2)
        users = append(users, userInfo)
    }
    
    return users
}

🎓 Summary

In this chapter, we comprehensively learned about using variables in Go:

  • Variable Declaration: var keyword, type inference, multi-variable declaration
  • Short Variable Declaration: usage and precautions of := operator
  • Variable Scope: global variables, local variables, variable shadowing
  • Variable Initialization: zero values, explicit initialization
  • Variable Assignment: basic assignment, multiple assignment, increment/decrement
  • Variable Lifecycle: stack vs heap, escape analysis
  • Naming Conventions: naming styles and best practices

Mastering proper use of variables is a fundamental skill in Go programming. Good variable naming and scope management can improve code readability and maintainability.


Next, we will learn Go Constants to understand how to define and use immutable values.

Variable Usage Suggestions

  • Prefer using short variable declaration := for declaring variables inside functions
  • Use meaningful variable names, avoid meaningless abbreviations
  • Use variable scope reasonably, avoid unnecessary global variables
  • Pay attention to variable lifecycle to avoid memory leaks

Content is for learning and research only.