【问题标题】:Why I can redefine the same variable multiple times in a for loop but can't outside of a loop?为什么我可以在 for 循环中多次重新定义同一个变量,但不能在循环之外?
【发布时间】:2016-08-29 14:00:06
【问题描述】:

我有以下程序。

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)
}

我将收到错误“:= 左侧没有新变量”。为什么会这样?

【问题讨论】:

标签: variables go


【解决方案1】:

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

声明变量的默认方法是使用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 在该范围内不存在。

【讨论】:

    【解决方案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?

    【讨论】:

    • 我很惊讶后者是允许的(例如,在内部范围内设置a := 78,然后在函数返回之前检查a。我花了几个小时追踪一个由于变量在内部范围内重新设置,稍后在外部范围内使用而无需修改。Go 的编译器对其他事情很严格,为什么不这样做?(很难看到,因为 := 不是那么明显就像使用 var 关键字一样)。
    猜你喜欢
    • 2019-08-20
    • 2018-09-21
    • 1970-01-01
    • 2020-02-05
    • 2020-04-05
    • 2016-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多