在Golang中,为什么我可以在for循环中多次重新定义相同的变量但不能在循环之外?

时间:2016-08-29 14:00:06

标签: variables go

我有以下程序。

package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 2; i++ {
        x := 77
        fmt.Println(x)
    }
}

执行时我得到了:

77
77

我们可以看到,x := 77已执行2次。但是,如果我稍微修改它:

package main

import (
    "fmt"
)

func main() {
    a := 77
    fmt.Println(a)
    a := 77
    fmt.Println(a)
}

我会收到错误“:=左侧没有新变量”。为什么这个?有人可以帮忙解释一下吗?提前谢谢。

2 个答案:

答案 0 :(得分:9)

这里有几件事。首先让我们解决你问题的后半部分。

声明变量的默认方式是使用var关键字,然后使用=运算符分配给它。

var a int
a = 77

Go允许我们使用快捷方式:=,它既声明变量又赋值

a := 77

在您的示例中,第二次使用:=时,您尝试在同一范围内重新声明名为a的新变量,这是不允许的。错误no new variables on left side of :=正试图告诉您这一点。

但是现在问到你原来的问题,为什么你能在for循环中多次这样做?

原因是每次输入大括号{}块时,您都在创建一个新的嵌套范围。当您在循环顶部声明变量x时,它是一个新变量,并且在循环结束时超出范围。当程序再次回到循环的顶部时,它又是另一个新范围。

例如,查看此代码

{
    x := 77
    fmt.Println(x)
}
fmt.Println(x) // Compile error

第二个Println失败,因为该范围内不存在x

答案 1 :(得分:2)

没有标识符可以在同一个文件中声明两次  块,并且文件和包中都不能声明标识符  块。

请参阅:What is the difference between := and = in Go?

此处for每次运行都有新变量,
此代码通过打印x的地址来显示 (The Go Playground):

package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 2; i++ {
        x := 77
        fmt.Println(&x)
    }
}

输出:

0x1040e0f8
0x1040e0fc

如果您在第二个示例中需要新变量,则可能会影响它 (The Go Playground):

package main

import (
    "fmt"
)

func main() {
    a := 77
    fmt.Println(&a)
    {
        a := 77
        fmt.Println(&a)
    }
}

输出:

0x1040e0f8
0x1040e0fc

另见:Where can we use Variable Scoping and Shadowing in Go?