作用域指的是变量、常量、类型和函数等标识符在代码中的有效范围。Go 语言采用词法作用域(静态作用域),作用域由代码块的位置决定,编译期就可以确定。
1. 四种常见作用域
从大到小依次是:包级作用域、文件级作用域、函数级作用域和代码块级作用域。
包级作用域:在函数外声明的标识符,对整个包的所有文件可见,首字母大写的还可以被其他包访问。函数级作用域:在函数内声明的变量,只在函数体内有效。代码块级作用域:在 if、for、switch 等语句块内声明的变量,只在块内有效。
var global = "包级变量"
func main() {
local := "函数级变量"
if true {
inner := "块级变量"
fmt.Println(global, local, inner) // 都能访问
}
// fmt.Println(inner) // 编译错误:inner 未定义
}
2. 变量遮蔽
内层作用域声明了和外层同名的变量时,内层变量会遮蔽外层变量,这种写法容易造成误读:
name := "外层"
if true {
name := "内层" // 遮蔽了外层的 name
fmt.Println(name) // 内层
}
fmt.Println(name) // 外层
特别注意 := 与 = 的区别:在 if 语句中使用 := 声明的变量属于 if 自己的作用域:
if n, err := strconv.Atoi("123"); err == nil {
fmt.Println(n)
}
// fmt.Println(n) // 编译错误,n 只在 if 中可用
3. 查找顺序
使用一个变量时,编译器按「内层到外层」的顺序查找:先找当前块,再找外层函数,最后找包级作用域。找到最近的声明就停止,这就是遮蔽生效的原因。
编写代码时建议避免不同作用域使用同名变量,可以用 go vet 和 linters(如 shadow 检查)辅助发现遮蔽问题。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END









暂无评论内容