一、变量(Variable)

1. 变量声明方式

Go语言提供了多种变量声明方式,灵活适应不同场景:

  • 标准声明:使用 var 关键字,显式指定类型和值。

    var a int = 10
    var b string = "hello"
    
  • 同时赋初值:声明时直接赋值,类型可省略(由编译器推导)。

    var c = 30       // 类型推导为 int
    var name = "Go"  // 类型推导为 string
    
  • 短变量声明:仅限函数内部使用,使用 := 自动推导类型。

    d := 40          // 类型推导为 int
    e := "world"     // 类型推导为 string
    
  • 多变量声明:一次声明多个变量,支持混合类型。

    var x, y, z int = 1, 2, 3
    var (
      name string = "Go"
      age  int    = 14
      flag bool   = true
    )
    

2. 零值(Zero Value)

未显式初始化的变量会被赋予类型的零值:

  • 数字类型:0
  • 布尔类型:false
  • 字符串类型:""
  • 指针/引用类型:nil

示例:

var count int      // count 的值为 0
var text string    // text 的值为空字符串 ""
var ptr *int       // ptr 的值为 nil

3. 变量作用域

  • 全局变量:在包级别(函数外部)声明,整个包可见。

    package main
    var globalVar = "I'm global"
    
  • 局部变量:在函数内部声明,仅在函数内有效。

    func main() {
      localVar := "I'm local"
      fmt.Println(localVar) // 正确
    }
    

4. 变量注意事项

  • 短变量声明不能重复声明:= 只能用于声明新变量,不能重复声明已有变量。

    a := 10
    a := 20 // 编译错误:重复声明
    
  • 变量未使用会导致编译错误:Go语言强制代码整洁,未使用的变量会报错。

    func main() {
      unusedVar := 100 // 编译错误:unusedVar declared but not used
    }
    
  • 类型转换必须显式声明

    var a float32 = 1.1
    b := int(a) // 显式转换
    

5. 示例代码

package main
import "fmt"

func main() {
    // 标准声明
    var x int = 100
    fmt.Println("x:", x)

    // 短变量声明
    y := 200
    fmt.Println("y:", y)

    // 多变量声明
    var a, b, c = 1, 2, "Go"
    fmt.Println("a, b, c:", a, b, c)

    // 零值示例
    var str string
    fmt.Println("str:", str) // 输出空字符串
}

二、常量(Constant)

1. 常量声明方式

常量使用 const 关键字声明,值在编译时确定且不可变:

  • 单个常量声明

    const Pi = 3.14
    const Name string = "GoLang"
    
  • 多常量声明:使用括号一次性声明多个常量。

    const (
      A = 1
      B = "hello"
      C = true
    )
    
  • iota 枚举常量iota 是常量计数器,从0开始递增。

    const (
      Red = iota // 0
      Green      // 1
      Blue       // 2
    )
    

2. iota 的高级用法

  • 连续枚举

    const (
      Monday = iota + 1 // 1
      Tuesday           // 2
      Wednesday         // 3
    )
    
  • 位运算iota 结合左移操作符定义权限位。

    const (
      Read = 1 << iota // 1 (binary: 0001)
      Write            // 2 (binary: 0010)
      Execute          // 4 (binary: 0100)
    )
    
  • 弃用枚举值:使用 _ 忽略特定枚举值。

    const (
      _ = iota // 0 被弃用
      KB = 1 << (10 * iota) // 1KB = 1024^1
      MB                    // 1MB = 1024^2
      GB                    // 1GB = 1024^3
    )
    

3. 未定类常量(Untyped Constants)

未显式指定类型的常量称为未定类常量,具有更高的灵活性:

const MaxValue = 100    // 未定类整数常量
const Greeting = "Hello" // 未定类字符串常量

4. 常量注意事项

  • 常量值必须在编译时确定:不能使用运行时函数或变量。

    const Max = len("abc") // 正确:len 是编译时常量
    const Min = math.Min(1, 2) // 错误:math.Min 是运行时函数
    
  • 常量不能使用短变量声明:必须使用 const

    const PI := 3.14 // 错误:const 不能与 := 混用
    
  • 常量类型转换:未定类常量可以隐式转换为其他类型。

    const a = 100
    var b int16 = a // 正确:未定类常量 a 隐式转换为 int16
    

5. 示例代码

package main
import "fmt"

func main() {
    // 单个常量声明
    const Pi = 3.14
    fmt.Println("Pi:", Pi)

    // 多常量声明
    const (
        MaxUsers = 100
        AppName  = "MyApp"
    )
    fmt.Println("MaxUsers:", MaxUsers, "AppName:", AppName)

    // iota 枚举
    const (
        Spring = iota
        Summer
        Autumn
        Winter
    )
    fmt.Println("Seasons:", Spring, Summer, Autumn, Winter)

    // 位运算
    const (
        Read = 1 << iota
        Write
        Execute
    )
    fmt.Printf("Read: %b, Write: %b, Execute: %b\n", Read, Write, Execute)

    // 未定类常量
    const Value = 100
    var a int8 = Value // 正确:隐式转换
    var b float64 = Value // 正确:隐式转换
    fmt.Println("a:", a, "b:", b)
}

三、变量与常量的区别

项目变量常量
是否可变
是否必须赋值否(有零值)
作用域全局/局部全局/局部
类型推导支持支持
典型用途临时状态、动态数据数据配置、不变值
声明方式var:=const
短声明限制仅限函数内部不支持短声明
未使用变量导致编译错误无此限制

四、总结

  • 变量:用于存储可能变化的数据,声明方式灵活,支持类型推导。
  • 常量:用于存储不可变的数据,支持 iota 枚举和未定类常量,提升代码可读性和安全性。
  • 最佳实践:优先使用短变量声明(:=)简化代码,常量用于固定值(如配置、枚举),避免魔法数字。

通过合理使用变量和常量,可以提高代码的可维护性和性能,同时遵循Go语言的简洁与安全设计理念。