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

I have the following program.

package main

import (
    "fmt"
)

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

When executed I got:

77
77

As we can see, the x := 77 has been execute 2 times. However, If I modify it slightly like this:

package main

import (
    "fmt"
)

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

I will get the error "no new variables on left side of :=". Why this? Can anyone help to explain it please? Thanks in advance.

doqau82086
doqau82086 这确实不是Golang特有的。任何语言的行为都相似。
接近 4 年之前 回复
douzhuan1169
douzhuan1169 在规范中:golang.org/ref/spec#Declarations_and_scope
接近 4 年之前 回复

2个回答



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

声明变量的默认方法是使用 var </ code>关键字,然后使用 = </ code>运算符。</ p>

  var a int 
a = 77
</ code> </ pre>

Go为我们提供了一条捷径 := </ code>都声明一个变量并分配一个值</ p>

  a:= 77 
</ code> </ pre>

在您的示例中,当您第二次使用:= </ code>时,您试图在不允许的同一范围内重新声明一个名为 a </ code>的新变量。 错误:= </ code>左侧没有新变量正在尝试告诉您。</ p>

但是现在您的原始问题是,为什么可以多次执行此操作? 是在for循环内?</ p>

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

例如,查看此代码</ p>

  {

x:= 77
fmt.Println(x)
}
fmt.Println(x)//编译错误
</ code> </ pre>

第二个 Println </ code>失败,因为该范围中不存在 x </ code>。</ p>
</ div>

展开原文

原文

There are a couple of things here. First let's address the second half of your question.

The default way to declare a variable is using the var keyword and then assign to it with the = operator.

var a int
a = 77

Go allows us a shortcut := that both declares a variable and assigns a value

a := 77

In your example when you use := a second time you're trying to redeclare a new variable named a in the same scope which is not allowed. The error no new variables on left side of := is trying to tell you this.

But now to your original question, why can you do this multiple times inside a for loop?

The reason is each time you enter a block of curly braces {} you're creating a new nested scope. When you declare the variable x at the top of the loop it is a new variable and it goes out of scope at the end of the loop. When the program comes back around to the top of the loop again it's another new scope.

For example look at this code

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

That second Println fails because x does not exist in that scope.

No identifier may be declared twice in the same block, and no identifier may be declared in both the file and package block.

And see: What is the difference between := and = in Go?


You have new variable on each run of for here,
This code shows it by printing the address of x (The Go Playground):

package main

import (
    "fmt"
)

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

output:

0x1040e0f8
0x1040e0fc

And if you need new variable in your second example you may shadow it (The Go Playground):

package main

import (
    "fmt"
)

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

output:

0x1040e0f8
0x1040e0fc

Also See: Where can we use Variable Scoping and Shadowing in Go?

douqiao1997
douqiao1997 我很惊讶后者被允许使用(例如,在内部作用域内设置:= 78,然后在函数返回之前检查a。我只是花了几个小时来追查由于在内部变量中重新设置了变量而导致的错误) Go的编译器在其他方面很严格,为什么不这样做呢(很难看到,因为:=不如使用var关键字那么明显)。
大约 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问