跳到主要内容

Go 变量作用域

提示
  1. 局部变量和全局变量:在 Go 中,局部变量在函数内声明,仅限于该函数内访问。全局变量在 main() 函数之前声明,可在程序任何地方访问。
  2. 作用域和可访问性:局部变量的作用域限于定义它们的函数内部,而全局变量在整个程序中都是可访问的。
  3. 局部变量优先级:如果局部变量和全局变量具有相同的名称,编译器会优先使用局部变量。全局变量可能导致程序中的值不一致,因此在某些情况下不推荐使用。

在 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 中,intfloat32 类型的默认值是 0

// 程序演示全局和局部变量的默认值

package main
import "fmt"

// 全局变量
var variable1 int

func defaultValues() {

// 局部变量
var variable2 float32

fmt.Println(variable1) // 0
fmt.Println(variable2) // 0

}

func main() {
defaultValues()
}

在上述示例中,我们已经初始化了局部和全局变量。不管它在哪里初始化,intfloat32 的默认值都是 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() 认为值与其定义的相同,并根据那个值继续执行。

这可能会导致意外的输出,并在更大的程序中造成高度混乱。