Go语言变量与常量

变量是程序存储数据的基本单位,常量则用于表示固定不变的值。Go语言在变量和常量的设计上既保持了静态类型的安全性,又通过类型推断和简洁的语法提供了动态语言的灵活性。本章将详细讲解Go中变量与常量的声明、初始化、作用域以及特殊用法。

核心要点:Go中未使用的变量会引发编译错误;短变量声明 := 是函数内部最常用的方式;常量在编译时求值,只能是基本类型。

变量声明

Go是静态强类型语言,但支持类型推断,使得声明变量有多种形式。

1.1 标准声明:var name type

标准声明示例
package main

import "fmt"

func main() {
    var name string      // 声明一个 string 变量,初始值为零值 ""
    var age int          // 零值为 0
    var isActive bool    // 零值为 false

    name = "Alice"
    age = 30
    isActive = true

    fmt.Println(name, age, isActive)
}

1.2 声明并初始化

var city string = "Beijing"
var score int = 95
var flag bool = true

1.3 类型推断(省略类型)

编译器会根据初始值自动推断变量类型。

var name = "Bob"      // 推断为 string
var age = 25          // 推断为 int
var pi = 3.14159      // 推断为 float64

1.4 短变量声明(最常用)

在函数内部,可以使用 := 代替 var 声明并初始化,类型由编译器推断。

func main() {
    message := "Hello, Go"   // 等价于 var message string = "Hello, Go"
    count := 10
    ratio := 0.618
    // 注意:短变量声明不能用于全局变量(包级作用域)
}
注意:短变量声明左侧至少有一个新变量,否则会编译错误。例如 count := 5; count := 10 会报错(重复声明),但可以使用赋值 count = 10。

1.5 多变量声明

// 使用 var
var x, y int = 10, 20
var a, b = "foo", true

// 短变量声明
c, d := 3.14, "pi"

// 批量声明(适合包级变量)
var (
    username string = "admin"
    port     int    = 8080
    enabled  bool   = true
)

零值机制

在Go中,变量声明后如果不显式初始化,会被自动赋予其类型的零值(默认值)。这一特性保证了变量始终处于可用状态,避免了未初始化的随机值问题。

类型零值
数值类型(int, float, complex)0
布尔类型 boolfalse
字符串 string""(空字符串)
指针、切片、map、通道、函数、接口nil
数组、结构体内部每个元素/字段的零值
var i int          // 0
var f float64      // 0.0
var b bool         // false
var s string       // ""
var p *int         // nil
var arr [3]int     // [0, 0, 0]
var slice []int    // nil (但 nil 切片可以 append)
var m map[string]int // nil (不能直接赋值,需要用 make 初始化)

作用域与命名规则

  • 包级变量:在函数外部声明,可以在整个包内访问(首字母小写),如果首字母大写则可以被其他包导入访问(导出变量)。
  • 局部变量:在函数或代码块内声明,作用域仅限于该块。
  • 变量命名规则:以字母或下划线开头,后跟字母、数字或下划线。推荐使用驼峰式(如 userName)。Go中首字母大写表示公开(public),小写表示私有(private)。
package main

var globalVar = "I am global"     // 包级私有变量
var ExportedVar = "I am exported" // 可被其他包访问

func main() {
    localVar := "I am local"
    {
        innerVar := "inside block"
        fmt.Println(innerVar)
    }
    // fmt.Println(innerVar) // 编译错误:innerVar 不可见
}

常量

常量使用 const 关键字声明,其值在编译时确定,程序运行时不可改变。常量可以是无类型常量(更灵活)或有类型常量。

4.1 基本常量声明

const Pi = 3.14159                 // 无类型浮点常量
const StatusOK = 200               // 无类型整数常量
const (
    Monday = "Monday"
    Tuesday = "Tuesday"
)
const (
    a = 1
    b          // 省略值表示与上一行相同,即 b = 1
)
const c int = 100                  // 有类型常量

4.2 常量枚举与 iota

iota 是Go内置的常量生成器,在 const 块中每次出现时自增1,初始为0。常用于生成枚举值。

const (
    Sunday = iota     // 0
    Monday            // 1
    Tuesday           // 2
    Wednesday         // 3
    Thursday          // 4
    Friday            // 5
    Saturday          // 6
)

const (
    _ = iota          // 0,跳过
    KB = 1 << (10 * iota)  // 1 << 10 = 1024
    MB = 1 << (10 * iota)  // 1 << 20 = 1048576
    GB = 1 << (10 * iota)  // 1 << 30
)

// 自定义表达式
const (
    A = iota * 2   // 0
    B              // 2
    C              // 4
)
iota 原理:每个 const 块中的 iota 从0开始,每出现一次(包括新行)自动增加1。遇到新的 const 块时 iota 重置为0。

类型推断与类型转换

Go中变量一旦声明为某种类型,不能隐式转换为其他类型,必须显式转换。

var i int = 42
var f float64 = float64(i)   // 显式转换
var u uint = uint(f)

// 不同类型变量不能直接赋值或比较
// var x int = 10
// var y float64 = x   // 编译错误

// 常量可以自动转换(因为常量是无类型的)
const ci = 10
var f2 float64 = ci   // 允许,ci 作为无类型常量被转换为 float64

综合示例

变量与常量实战
package main

import "fmt"

// 包级常量
const (
    AppName = "GoCalculator"
    Version = "1.0.0"
)

// 包级变量(零值初始化)
var result float64

func main() {
    // 局部变量
    a := 10.5
    b := 20.3

    // 使用常量
    fmt.Printf("%s v%s\n", AppName, Version)

    // 运算
    result = a + b
    fmt.Printf("%g + %g = %g\n", a, b, result)

    // 类型转换示例
    var count int = 5
    avg := result / float64(count)  // 必须显式转换
    fmt.Printf("Average: %.2f\n", avg)

    // iota 枚举
    const (
        StatusPending = iota
        StatusRunning
        StatusCompleted
        StatusFailed
    )
    fmt.Println("Status Pending:", StatusPending)   // 0
    fmt.Println("Status Running:", StatusRunning)   // 1
}

运行输出:

GoCalculator v1.0.0
10.5 + 20.3 = 30.8
Average: 6.16
Status Pending: 0
Status Running: 1
小结:掌握变量与常量是学习Go语言的基础。下一章我们将学习Go的基本数据类型,包括整型、浮点型、布尔型、字符串以及类型转换的细节。