3.4 Go函数作用域(标识符)
只有精准分析每个标识符的作用域范围,才能编写出优质、健壮的代码,避免逻辑错误的发生。
作用域==标识符
简单来说,作用域指的是标识符可以起作用的范围,即其可见范围。将标识符的可见性限制在一定范围内,这个范围就是作用域。
把标识符约束在一定的可见范围内,这个范围就是作用域。
1. 宇宙块
宇宙块是 Go 语言内建的作用域范围,由 Go 编译器定义,我们无法在代码中手动创建或扩展宇宙块。简单来说,它只包括 Go 内置的标识符,不存在宇宙冲突的情况。
- 特点:预定义标识符,任何地方都可以使用。
- Go 内建的标识符,例如 true、false、nil 等,它们是预定义的,始终可用。
- 是否需要加包名:不需要。
2. 包块
目的:
- 为了隔离,避免全局标识符(变量)冲突、污染问题
- 将若干行代码分散在不同目录的不同的.go文件中(按不同的目录和文件进行隔离)
package main
var a=1024 //一般说全局变量是指某个包的全局变量,包全局变量写在包内的顶层代码
func main() {
fmt.Println(a)
}
-
- 类型:package块,属于全局作用域。
- 定义:在包内顶层代码中定义的全局常量或全局变量。
- 对外可见性:
-
- 包内随处可用
- 首字母大写:包外可见。使用时通过 包名.标识符 访问。包内也能直接使用,无需加包名。
- 首字母小写:仅包内可见,使用时无需加包名 。
3. 局部块
- 定义在局部代码块中的变量,例如 if、switch、for 、select、case等语句内使用 := 定义的变量。
- 可见范围:仅限于所在语句块,无法在块外访问。
- 注意:局部变量的作用范围比全局变量更小。即使全局变量在函数中定义,其作用范围也比函数内的局部变量大。
4.包全局
- 写在包内顶层代码
- 全局常量标识符、全局变量标识符
- 包内随处可用,不需要使用包名.
如果两个变量或函数在同一个包中命名相同,编译时会报错,需要开发者自己来解决。
package main
const a = 100 //常量小写,只能在main包内使用,包内全局变量
var b = 200 //变量小写,只能在main包内使用,包内全局变量,未导出
func main() {
// a = a + 1024 //常量不可修改
// fmt.Println(a,&a) //常量不可取地址
var a=2048 //为main定义全局变量 a,此a不是外部的包全局变量
fmt.Println(a) //常量不可取地址
fmt.Println(b)
}
5.函数块
函数定义有{},函数看做一个块
block{},内部可以写n条语句,语句中定义的变量,属于当前块的
func main() {
switch a := 100; {
case a > 0:
fmt.Println(100, a)
}
// fmt.Println(a) //在switch 外部不能访问到switch定义的变量 a
s := []int{1, 2, 3, 4}
for i, v := range s {
fmt.Println(i, v)
}
fmt.Println(i, v) //超出其作用域不可见
if f, err := os.Open("o:/main.go"); err != nil {
fmt.Println(f, err) // 变量在if 内部可见
}
fmt.Println(f, err) //错误,if 外部不可见。
}