[英]Why a short variable declaration in an else if statement doesn't fail to compile even though no new variable is being defined on the left side?
以下代碼預計會因編譯錯誤而失敗:
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)
}
}
這是 output:
else if block: x: 11
為什么即使else if x:= x + 1
中的:=
運算符沒有定義任何新變量,第二個程序也會成功?
根據 Go 規范,這里是if
語句的定義方式:
IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ].
后來,在聲明和 Scope部分中說:
在塊中聲明的標識符可以在內部塊中重新聲明。 內部聲明的標識符在 scope 中,表示內部聲明所聲明的實體。
現在, if
語句是一個隱式塊:
每個“if”、“for”和“switch”語句都被認為在其自己的隱式塊中。
然后從IfStmt
定義中可以看出,在關鍵字else
之后可能會出現:
Block
,即else { /* code */ }
IfStmt
再次,就像你的情況一樣,即else if /* statement */ { /* code */ }
。 這意味着IfStmt
是遞歸的,它是另一個IfStmt
中的隱式塊(仍然是隱式塊)。 因此它滿足重新聲明標識符的條件。還與顯式塊進行比較:
func foo() {
x := 10
{
x := 20
fmt.Println("Inner x:", x) // 20
}
fmt.Println("Outer x:", x) // 10
}
由於您的第二個 x:= 在另一個 scope 中,您正在處理兩個不同的 x 變量。 所以它對你來說看起來像同一個 x,但它不是,即使它基於外部 x 的值,它也不會影響它。 您正在打印的 x 是內部 x。
考慮這個例子:
package main
import (
"fmt"
)
func main() {
// Define x in the func scope
x := 10
// Print out global scope x
fmt.Printf("x1:%v\n", x)
// Not allowed (x already defined in this scope)
//x := x + 1
// Allowed (different x)
{
x := x + 1
// Print new local scope x (this is a second x)
fmt.Printf("x2:%v\n", x)
}
// Allowed (different x defined)
if x := x + 1; x > 10 {
// Print new local scope x (this is a third x)
fmt.Printf("x3:%v\n", x)
}
// Print out global scope x
fmt.Printf("x1:%v\n", x)
}
在此示例中,您有 3 個 x 變量。 func 級別第一,{} 中的第一個作用域,然后是 if 塊中的另一個(再次獨立)。 所有這三個都是獨立的,並且兩個內部的在定義后(在該范圍內)會影響外部的,因此即使您選擇將 x 2 和 3 設為初始 x 的基礎,它們也不會影響其值。
當您在末尾打印出全局 scope x 時,您可以看到這一點,並且因為 x3 不受 x2 值的影響,所以我們最終在 function 的末尾:
在這個例子中,
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)
}
}
您在兩個地方定義 x 變量是正確的,因為該變量的 scope 在 if 和 else 下。 像這樣考慮這段代碼
如果你在這里看到我們有兩個街區,街區 1 和街區 2
兩個塊都有自己的 scope,無論您在該塊內部定義什么,外部都無法訪問。
試試這個,你會得到一個錯誤。
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)
}
fmt.Println("What is the value of x: ", x)
}
錯誤:./prog.go:13:45:未定義:x
因為您正試圖在外部訪問該變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.