Go 变量作用域
- 局部变量和全局变量:在 Go 中,局部变量在函数内声明,仅限于该函数内访问。全局变量在
main()
函数之前声明,可在程序任何地方访问。 - 作用域和可访问性:局部变量的作用域限于定义它们的函数内部,而全局变量在整个程序中都是可访问的。
- 局部变量优先级:如果局部变量和全局变量具有相同的名称,编译器会优先使用局部变量。全局变量可能导致程序中的值不一致,因此在某些情况下不推荐使用。
在 Go 中,我们可以在两个不同的作用域中声明变量:局部作用域和全局作用域。
变量的作用域指定了我们可以访问变量的区域。例如,
func addNumbers() {
sum := 5 + 4
}
这里,sum 变量是在函数内部创建的,所以它只能在函数内部访问(局部作用域)。这种类型的变量被称为局部变量。
根据作用域,我们可以将 Go 中的变量分为两类:
- 局部变量
- 全局变量
Go 局部变量
当我们在函数内部声明 变量时,这些变量将具有局部作用域(在函数内部)。我们不能在函数外部访问它们。
这些类型的变量被称为局部变量。例如,
// 程序演示局部变量
package main
import "fmt"
func addNumbers() {
// 局部变量
var sum int
sum = 5 + 9
}
func main() {
addNumbers()
// 无法在其局部作用域之外访问 sum
fmt.Println("Sum is", sum)
}
输出
undefined: sum
这里,sum 变量是 addNumbers()
函数的局部变量,所以它只能在函数内部访问。
这就是为什么我们在尝试从 main()
访问函数时会出现错误。
为了解决这个问题,我们可以返回局部变量的值并将其分配给 main 函数内的另一个变量。或者我们可以将变量 sum 声明为全局变量。
Golang 中的全局变量
当我们在 main()
函数之前声明变量时,这些变量将具有全局作用域。我们可以在程序的任何部分访问它们。
这些类型的变量被称为全局变量。例如,
// 程序演示全局变量
package main
import "fmt"
// 在 main 函数之前声明全局变量
var sum int
func addNumbers () {
// 局部变量
sum = 9 + 5
}
func main() {
addNumbers()
// 可以访问 sum
fmt.Println("Sum is", sum)
}
输出
Sum is 14
这次我们可以从 main()
函数内部访问 sum 变量。这是因为我们将 sum 变量创建为全局变量。
// 函数外部
var sum int
现在,sum 将可以在程序的任何作用域(区域)中访问。
常见问题
局部变量和全局变量的默认值是什么?
当我们在不分配任何值的情况下声明局部和全局变量时,它们将被分配给它们的默认值。
在 Go 中,int
和 float32
类型的默认值是 0。
// 程序演示全局和局部变量的默认值
package main
import "fmt"
// 全局变量
var variable1 int
func defaultValues() {
// 局部变量
var variable2 float32
fmt.Println(variable1) // 0
fmt.Println(variable2) // 0
}
func main() {
defaultValues()
}
在上述示例中,我们已经初始化了局部和全局变量。不管它在哪里初始化,int
和 float32
的默认值都是 0。
如果局部变量和全局变量同名会怎样?
如果我们有局部和全局变量具有相同的变量名,编译器会优先考虑局部变量。例如,
// 展示变量优先级的程序
package main
import "fmt"
// 定义全局变量
var random = "Global"
func main() {
// 定义具有相同名称的局部变量
var random = "Local"
fmt.Println(random)
}
输出
Local
这里,局部变量和全局变量都叫 random
。当我们打印 random
时,它打印的是 "Local" 而不是 "Global"。这意味着编译器优先考虑局部变量而不是全局变量。
为什么局部变量比全局变量更受青睐?
在某些情况下,使用全局变量被认为是不好的做法。这是因为全局变量可以在程序的任何部分被访问。
因此,当一个函数改变全局变量的值时,同一程序的其他函数可能不知道这个变化。这样可能会在全局变量的值中造成不一致。
让我们看一个例子。
// 查找温度的程序
package main
import "fmt"
// 全局变量
var temperature float32 = 35
func findTemp1() {
temperature = 43
}
func findTemp2() {
temperature = 29
}
func main() {
fmt.Println("初始值:", temperature)
findTemp1()
fmt.Println("findTemp1()后的值:", temperature)
findTemp2()
fmt.Println("findTemp2()后的值:", temperature)
}
输出
初始值: 35
findTemp1()后的值: 43
findTemp2()后的值: 29
这里,我们创建了两个函数来找到温度。当 findTemp2()
函数改变 temperature
的值时,findTemp1
可能不知道这个变化。因此,findTemp1()
认为值与其定义的相同,并根据那个值继续执行。
这可能会导致意外的输出,并在更大的程序中造成高度混乱。