本篇基于 Go 1.25.1 版本,带你彻底理解变量作用域,搞懂全局、局部、块级范围,再也不踩变量遮蔽的坑✅
一、什么是变量作用域?
一句话:
变量能被访问、使用的有效代码范围
超出范围 → 报错“未定义”
Go 作用域分 3 类:
- 1. 全局作用域
- 2. 函数/局部作用域
- 3. 块作用域(if/for/switch 内部)
二、作用域分类对照表(直接收藏)
| 类型 | 定义位置 | 访问范围 | 生命周期 |
|---|---|---|---|
| 全局变量 | 函数外、包内 | 整个包所有函数 | 程序全程 |
| 局部变量 | 函数内 | 当前函数内部 | 函数执行期间 |
| 块变量 | if/for/switch 内 | 当前代码块内部 | 块执行期间 |
三、逐类精讲 + 清晰示例
1. 全局作用域(包内全局)
函数外定义,整个包都能用
大写 → 包外可访问
小写 → 包内可访问
package main
// 全局变量
var globalMsg = "我是全局变量"
func main() {
fmt.Println(globalMsg) // 可访问
}2. 局部作用域(函数内)
函数内定义,只能在当前函数用
func test() {
localNum := 100 // 局部变量
fmt.Println(localNum)
}
func main() {
// fmt.Println(localNum) → 报错!
}3. 块作用域(if/for/switch 内部)
只在当前大括号{}内有效
if true {
blockVal := "我在if块里"
fmt.Println(blockVal) // 正常
}
// fmt.Println(blockVal) → 报错!四、重点规则:同名变量遮蔽(Shadow)
内部变量会覆盖/遮蔽外部同名变量
var num = 10 // 全局
func main() {
num := 20 // 局部遮蔽全局
fmt.Println(num) // 20
}五、完整可运行 Demo(全覆盖、可直接跑)
main.go 零语法错误,演示所有作用域👇
package main
import "fmt"
// ==================== 1. 全局变量(包内所有函数可用) ====================
var globalName = "Go全局变量"
var globalAge = 18
func main() {
fmt.Println("=== 1. 访问全局变量 ===")
fmt.Println("全局名称:", globalName)
// ==================== 2. 局部变量(仅 main 函数内可用) ====================
localMsg := "我是 main 函数局部变量"
fmt.Println("\n=== 2. 局部变量 ===")
fmt.Println(localMsg)
// ==================== 3. 块作用域(if 内部) ====================
fmt.Println("\n=== 3. if 块作用域 ===")
if true {
blockMsg := "我在 if 代码块里"
fmt.Println(blockMsg)
}
// fmt.Println(blockMsg) // 报错:超出作用域
// ==================== 4. 变量遮蔽(重点) ====================
fmt.Println("\n=== 4. 变量遮蔽 ===")
globalAge := 99 // 局部变量遮蔽全局
fmt.Println("局部 age:", globalAge)
fmt.Println("全局 age:", globalAge) // 内部优先
// 调用函数测试全局
testFunc()
}
// testFunc 测试全局变量
func testFunc() {
fmt.Println("\n=== testFunc 访问全局 ===")
fmt.Println("全局名称:", globalName)
// fmt.Println(localMsg) // 报错!
}运行命令
go run main.go运行结果
=== 1. 访问全局变量 ===
全局名称: Go全局变量
=== 2. 局部变量 ===
我是 main 函数局部变量
=== 3. if 块作用域 ===
我在 if 代码块里
=== 4. 变量遮蔽 ===
局部 age: 99
全局 age: 99
=== testFunc 访问全局 ===
全局名称: Go全局变量六、作用域核心规则(必背)
- 1. 外层变量 → 内层可访问
- 2. 内层变量 → 外层不可访问
- 3. 同名变量:内层覆盖外层(遮蔽)
- 4. 大括号
{}就是一个作用域 - 5. 全局变量生命周期 = 程序全程
七、新手避坑指南
- 1. ❌ 同名变量遮蔽导致逻辑错误
- 2. ❌ 超出块范围访问变量
- 3. ❌ 函数内访问另一个函数的局部变量
- 4. ✅ 尽量少用全局变量(不易维护)
- 5. ✅ 变量尽量定义在离使用最近的地方
📌 总结
- 1. 全局变量:函数外,整个包可用
- 2. 局部变量:函数内,仅当前函数
- 3. 块变量:
if/for内,仅当前{} - 4. 同名遮蔽:内部覆盖外部
- 5. 作用域越小越安全、越规范
一篇搞定 Go 变量作用域,写代码再也不踩范围坑✨
MiaoAll