【go语言】作用域

作用域指的是变量、常量、类型和函数等标识符在代码中的有效范围。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
喜欢就支持一下吧
点赞5 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容