Go 变量与常量
目录
变量和常量是编程中最基本的概念。Go 语言提供了灵活的变量声明方式,同时通过严格的编译检查来避免常见的错误。本篇将全面讲解 Go 中变量和常量的声明、命名规范、零值概念以及 iota 枚举器的用法。
变量声明
使用 var 关键字
Go 中使用 var 关键字声明变量,语法为 var 变量名 类型:
package main
import "fmt"
func main() {
var name string // 声明一个 string 类型变量
var age int // 声明一个 int 类型变量
var score float64 // 声明一个 float64 类型变量
name = "张三"
age = 25
score = 95.5
fmt.Println("姓名:", name)
fmt.Println("年龄:", age)
fmt.Println("分数:", score)
}声明时初始化
可以在声明变量的同时赋予初始值,Go 会自动推导类型:
package main
import "fmt"
func main() {
var name = "李四" // 类型推导为 string
var age = 30 // 类型推导为 int
var pi = 3.14159 // 类型推导为 float64
var isStudent = false // 类型推导为 bool
fmt.Printf("%T %T %T %T\n", name, age, pi, isStudent)
}显式指定类型
如果需要明确指定类型(而非让编译器推导),可以这样写:
var count int = 100
var price float32 = 9.99多变量声明
同时声明多个变量:
package main
import "fmt"
func main() {
// 方式一:逐个声明
var a, b, c int
a, b, c = 1, 2, 3
fmt.Println(a, b, c)
// 方式二:同时初始化
var x, y, z = 10, 20, 30
fmt.Println(x, y, z)
// 方式三:分组声明
var (
name string = "王五"
age int = 28
city string = "北京"
isVip bool = true
)
fmt.Println(name, age, city, isVip)
}短变量声明
在函数内部,可以使用 := 进行短变量声明,Go 会自动推导类型:
package main
import "fmt"
func main() {
name := "赵六" // 等价于 var name string = "赵六"
age := 22 // 等价于 var age int = 22
isMarried := false // 等价于 var isMarried bool = false
fmt.Println(name, age, isMarried)
}短变量声明的限制
- 只能在函数内部使用,包级变量必须用
var。 - 至少有一个新变量(如果变量已存在,则只赋值不重新声明):
package main
import "fmt"
func main() {
x := 10
y := 20
// x 已存在,y 是新变量,合法
x, y := 30, 40
fmt.Println(x, y) // 输出: 30 40
}变量命名规范
Go 的变量命名遵循以下规则:
- 由字母、数字、下划线组成,但不能以数字开头。
- 区分大小写:
name和Name是不同的变量。 - 推荐使用驼峰命名法(camelCase)。
首字母决定可见性
package user
// 首字母大写 —— 导出,其他包可访问
var DefaultRole = "guest"
// 首字母小写 —— 非导出,仅本包可访问
var maxLoginAttempts = 5命名建议
- 局部变量尽量用短名称:
i、n、err、ctx。 - 作用域越大,名称越要有意义:
userCount比n更好。 - 布尔变量常用
is、has、can前缀:isValid、hasError。
零值概念
Go 中声明变量但未显式赋值时,变量会被赋予其类型的零值:
| 类型 | 零值 |
|---|---|
int, int8, int16, int32, int64 |
0 |
uint, uint8, uint16, uint32, uint64 |
0 |
float32, float64 |
0.0 |
bool |
false |
string |
""(空字符串) |
| 指针、函数、接口、slice、channel、map | nil |
package main
import "fmt"
func main() {
var i int
var f float64
var b bool
var s string
var p *int
fmt.Printf("int: %d\n", i) // 0
fmt.Printf("float64: %f\n", f) // 0.000000
fmt.Printf("bool: %t\n", b) // false
fmt.Printf("string: %q\n", s) // ""
fmt.Printf("pointer: %v\n", p) // <nil>
}零值设计的好处是:变量声明后即可安全使用,不需要额外的初始化代码。
常量声明
常量使用 const 关键字声明,其值在编译时确定,不可修改:
package main
import "fmt"
func main() {
const pi = 3.14159265
const appName = "MyApp"
const maxRetry = 3
// pi = 3.14 // 编译错误:不能修改常量
fmt.Println(pi, appName, maxRetry)
}常量分组
const (
StatusPending = "pending"
StatusRunning = "running"
StatusComplete = "complete"
StatusFailed = "failed"
)无类型常量
Go 的常量可以没有显式类型,称为"无类型常量",它们可以兼容更多类型:
package main
import "fmt"
const threshold = 100 // 无类型常量
func main() {
var a int = threshold // 可以赋给 int
var b float64 = threshold // 可以赋给 float64
var c int64 = threshold // 可以赋给 int64
fmt.Println(a, b, c)
}iota 枚举器
iota 是 Go 的特殊常量生成器,每出现一次 iota,其值自动递增 1。它在常量组中从 0 开始计数。
基本用法
package main
import "fmt"
const (
a = iota // 0
b = iota // 1
c = iota // 2
d = iota // 3
)
func main() {
fmt.Println(a, b, c, d) // 输出: 0 1 2 3
}在同一常量组中,iota 可以省略不写(会自动沿用):
const (
a = iota // 0
b // 1
c // 2
d // 3
)实际应用:星期枚举
package main
import "fmt"
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
func main() {
fmt.Println("Sunday =", Sunday) // 0
fmt.Println("Monday =", Monday) // 1
fmt.Println("Friday =", Friday) // 5
fmt.Println("Saturday =", Saturday) // 6
}实际应用:文件大小单位
package main
import "fmt"
const (
B = 1 << (iota * 10) // 1
KB // 1024
MB // 1048576
GB // 1073741824
TB // 1099511627776
)
func main() {
fmt.Printf("B = %d\n", B)
fmt.Printf("KB = %d\n", KB)
fmt.Printf("MB = %d\n", MB)
fmt.Printf("GB = %d\n", GB)
fmt.Printf("TB = %d\n", TB)
}iota 跳过值
使用 _ 可以跳过某些 iota 值:
package main
import "fmt"
const (
A = iota // 0
_ // 1(跳过)
B = iota // 2
C // 3
)
func main() {
fmt.Println(A, B, C) // 输出: 0 2 3
}iota 配合表达式
package main
import "fmt"
const (
One = iota + 1 // 1
Two // 2
Three // 3
Four // 4
)
func main() {
fmt.Println(One, Two, Three, Four) // 输出: 1 2 3 4
}未使用变量的编译错误
Go 编译器严格要求:声明但未使用的变量会导致编译失败。这一设计避免了遗留无用变量的问题。
package main
import "fmt"
func main() {
x := 10
// fmt.Println("Hello")
// 编译错误:x declared but not used
}如果遇到确实需要声明但暂时不使用的变量,可以用 _ 丢弃:
package main
import "fmt"
func main() {
_ = 10 // 不会报错
// 函数返回多个值时,丢弃不需要的
// result, _ := someFunc()
fmt.Println("编译通过")
}总结
本篇全面介绍了 Go 中变量和常量的使用方式。变量可以通过 var 或 := 声明,未赋值时自动获得零值;常量通过 const 声明,配合 iota 可以方便地生成枚举值。Go 通过严格的编译检查(未使用变量报错、常量不可修改)来保证代码质量。命名方面,首字母的大小写决定了标识符的可见性,这是 Go 独特的访问控制方式。