Skip to content
目录

变量和常量详解

在 Go 语言中,变量和常量是构建程序的基本砖块。掌握它们的声明、初始化、作用域以及一些特殊规则(如变量遮蔽),对于编写健壮的 Go 代码至关重要。

1. 变量 (Variables)

变量是计算机内存中存储数据的容器。Go 语言是静态类型语言,变量声明时必须明确类型(或者由编译器推断)。

1.1 标准声明 (var)

使用 var 关键字声明变量,这是最基本的声明方式。

go
// 语法:var 变量名 类型 = 表达式
var name string = "王中阳"
var age int = 18

如果不提供初始值,变量会被初始化为零值(Zero Value):

  • int / float: 0
  • bool: false
  • string: "" (空字符串)
  • 指针 / 接口 / 切片 / map / channel / function: nil
go
var isBoy bool // false
var scores []int // nil

1.2 类型推断

如果提供了初始值,可以省略类型,编译器会自动推断:

go
var name = "Go语言" // 自动推断为 string
var age = 10        // 自动推断为 int

1.3 短变量声明 (:=)

这是 Go 语言中最常用的声明方式,只能在函数内部使用。

go
func main() {
    name := "Go语言"
    age, score := 18, 99.5
    
    fmt.Println(name, age, score)
}

注意事项

  1. := 左侧的变量必须至少有一个是新声明的,否则编译报错。
  2. := 不能在函数外部(全局作用域)使用。

1.4 批量声明

可以使用 var 块一次性声明多个变量,常用于声明全局变量:

go
var (
    a int
    b string
    c bool
)

1.5 匿名变量 (_)

在使用多重赋值时,如果不需要某个值,可以使用下划线 _(称为空白标识符)来忽略它。匿名变量不占用命名空间,不会分配内存。

go
func getNameAndAge() (string, int) {
    return "Tom", 20
}

func main() {
    // 只想要 name,忽略 age
    name, _ := getNameAndAge()
    fmt.Println(name)
}

1.6 变量作用域与遮蔽 (Shadowing)

这是新手容易踩的坑。如果在内部作用域声明了与外部作用域同名的变量,内部变量会遮蔽外部变量。

go
var x = 100

func main() {
    // 这里的 x 是一个新的局部变量,遮蔽了全局的 x
    x := 200 
    fmt.Println(x) // 输出 200
}

易错场景:在 iffor 中使用 := 意外遮蔽了外部变量。

go
func main() {
    x := 10
    if true {
        // 这里的 x 是 if 块内的局部变量
        x := 20
        fmt.Println(x) // 20
    }
    // 外部的 x 依然是 10
    fmt.Println(x) // 10
}

2. 常量 (Constants)

常量是在程序编译阶段就确定的值,程序运行时无法修改。

2.1 基本定义

使用 const 关键字定义。

go
const pi = 3.14159
const e = 2.7182

// 批量声明
const (
    StatusOk = 200
    NotFound = 404
)

2.2 自动填充

在批量声明中,如果省略后续行的赋值,它们会默认使用上一行的表达式。

go
const (
    n1 = 100
    n2 // 100
    n3 // 100
)

2.3 Iota 枚举器

iota 是 Go 语言的一个常量计数器,只能在常量的表达式中使用。

  • const 出现时,iota 被重置为 0。
  • const 中每新增一行常量声明,iota 计数加 1。

常用场景:定义枚举

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

进阶技巧:位掩码 (Bitmask)

利用 iota 和位运算(<<)可以优雅地定义权限或标志位。

go
const (
    _  = iota
    KB = 1 << (10 * iota) // 1 << 10 = 1024
    MB = 1 << (20)        // 1 << 20
    GB = 1 << (30)
    TB = 1 << (40)
)

3. 总结

  1. 优先使用 :=:在函数内部,尽量使用短变量声明,简洁明了。
  2. 警惕变量遮蔽:在嵌套代码块(if, for)中使用 := 时,要确认是否真的想要声明新变量,还是想修改外部变量(如果是修改,请用 =)。
  3. 善用 iota:在定义状态码、类型标识等枚举场景时,iota 能极大减少手动赋值的工作量。

扫描下方二维码,私信【训练营】可进行咨询和报名。 微信公众号二维码

🚀 学习遇到瓶颈?想进大厂?

看完这篇技术文章,如果还是觉得不够系统,或者想在实战中快速提升?
王中阳的就业陪跑训练营,提供定制化学习路线 + 企业级实战项目 + 简历优化 + 模拟面试。

了解训练营详情