在for循环中的短格式变量声明

huangapple go评论81阅读模式
英文:

Short format var declaration in for loop

问题

请看下面的代码。在Go语言中,(A)是不正确的,我明白为什么。但是为什么(B)在Go语言中是正确的呢?

(A)是不正确的:因为a的重新定义(在:=的左侧没有新的变量)

(B)也应该是一个错误:因为循环将在每次迭代时执行r :=,而r仍然在作用域内。

package main

import "fmt"

func main() {
    a := make([]byte, 10)
    fmt.Println(a)
    a := make([]byte, 10) //不正确,我明白为什么:(A)
    fmt.Println(a)

    for i := 0; i < 5; i++ {
        r := make([]byte, 10) //正确,但为什么这是正确的呢?:(B)
        fmt.Println(r)
    }
}
英文:

Please see the code below. (A) is not ok in Go and I understand why. But why is (B) ok in Go ?

(A) is not ok: because re-definition of a (no new var in LHS of := )

(B) should be an error too: because re-definition of r (no new var in LHS of := ) as the loop will execute r := with each iteration while r is still in scope.

package main

import &quot;fmt&quot;

func main() {
	a := make([]byte, 10)
	fmt.Println(a)
	a := make([]byte, 10) //not ok and I understand why : (A)
	fmt.Println(a)

	for i := 0; i &lt; 5; i++ {
		r := make([]byte, 10) //ok, but why is this ok? : (B)
		fmt.Println(r)
	}
}

答案1

得分: 4

短格式声明的关键思想是它必须在当前代码块中定义至少一个新变量。因此,在第一个示例中,它无法成功,因为它试图在当前代码块中重新定义 a,而没有引入任何新变量。而第二个代码块有效,因为 r 是在当前代码块中声明的一个新变量。

英文:

The key idea behind the short format declaration is that it has to define at least one new variable in the current block. So it fails in the first case because it is attempting to redefine a in the current block without introducing any new variables. The second block works, because r is a new variable declared in the current block.

答案2

得分: 3

根据go doc规范中关于短变量声明的描述,它在作用域中是临时的。

与常规变量声明不同,短变量声明可以重新声明变量,前提是它们在同一代码块中(或者如果代码块是函数体,则在参数列表中)最初已经声明过,并且至少有一个非空白变量是新的。因此,重新声明只能出现在多变量的短变量声明中。重新声明不会引入新变量;它只是给原变量赋予新值。

短变量声明只能出现在函数内部。在某些上下文中,比如"if"、"for"或"switch"语句的初始化器中,它们可以用来声明局部临时变量。

在同一作用域中,你不能使用短变量声明重新声明相同的变量。

a, a := 1, 2                              // 非法:重复声明a或者如果a在其他地方已经声明,则没有新变量

在你的情况下,r在循环作用域中,每次迭代r都是一个新变量。因为for循环会重复执行一个代码块。

for i := 0; i < 5; i++ {
    r := make([]byte, 10) // 这样是合法的,但为什么合法呢?:(B)
    fmt.Printf("%p\n", r)
}

如果你需要澄清这一点,请运行上述循环代码,并查看每次迭代中r的内存地址。它将打印出五个不同的地址。

英文:

As describe in go doc specifications about Short_variable_declarations, it is temporary for the scope.

> Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.
>
> Short variable declarations may appear only inside functions. In some contexts such as the initializers for "if", "for", or "switch" statements, they can be used to declare local temporary variables.

You can not redeclare same variable with short variable declaration in same scope.

a, a := 1, 2                              // illegal: double declaration of a or no new variable if a was declared elsewhere

In your case, r is in loop scope and each iteration r is a new variable. Because for loop repeats execution of a block.

> A "for" statement specifies repeated execution of a block

If you need to clarify this please run below loop code and see r's memory addresses for each iterations. It will print five different addresses.

    for i := 0; i &lt; 5; i++ {
		r := make([]byte, 10) //ok, but why is this ok? : (B)
		fmt.Printf(&quot;%p\n&quot;,r)
	}

huangapple
  • 本文由 发表于 2021年8月20日 09:50:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/68856120.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定