go - 为什么 `else if x := x + 1` 即使没有在 := 左侧定义新变量也不会编译失败

标签 go syntax grammar semantics

以下代码预计会在编译时失败并出现错误:

package main

import (
    "fmt"
)

func main() {
    x := 10
    x := x + 1
    fmt.Println(x)
}
编译错误是:
./prog.go:9:4: no new variables on left side of :=
所以我期待这段代码也会因错误而失败:
package main

import (
    "fmt"
)

func main() {
    if x := 10; x < 10 {
        fmt.Println("if block: x:", x)
    } else if x := x + 1; x < 20 {
        fmt.Println("else if block: x: ", x)
    }
}
这是输出:
else if block: x:  11
为什么即使 := 中的 else if x := x + 1 运算符没有定义任何新变量,第二个程序也会成功?

最佳答案

根据 Go 规范,以下是 if 语句的定义方式:IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] .后来,在 Declarations and Scope 部分中说:

An identifier declared in a block may be redeclared in an inner block. While the identifier of the inner declaration is in scope, it denotes the entity declared by the inner declaration.


所以现在, if 语句是一个 implicit block :

Each "if", "for", and "switch" statement is considered to be in its own implicit block.


那么从IfStmt的定义中可以看出,在关键字else之后可能又会出现一个IfStmt,它是中的一个隐式块,另一个IfStmt(仍然是一个隐式块),满足重新声明标识符的条件。
也与显式块进行比较:
func foo() {
    x := 10
    {
        x := 20
        fmt.Println("Inner x:", x) // 20
    }
    fmt.Println("Outer x:", x) // 10
}

关于go - 为什么 `else if x := x + 1` 即使没有在 := 左侧定义新变量也不会编译失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63272034/

相关文章:

json - 如何创建一个可以由 Gin 序列化为 json 的排序键值映射?

go - 无法导入私有(private) gitlab 存储库

antlr - ANTLR中是否存在逻辑AND和NOT?

html - HTML 是上下文无关语言吗?

go - 无法更新结构中的 map slice

mysql - SQL建表主键和外键语法

scala - 奇怪的Scala语法,其中映射Future以便 “==”和 “!=”仅出现一个操作数(而不是两个)

javascript - 为什么要设计一个库来使用 const [] 而不是 Javascript 中的 const {}?

parsing - 可组合语法

Golang - 将 int 添加到字节数组的末尾