我写了一个我在游乐场看到的问题的例子: https://play.golang.org/p/rPCqAC56Ff
这很明显,但是我在if语句之外声明一个变量,在if中设置变量然后在if之外使用。
问题很简单,为什么这不起作用?
package main
import (
"fmt"
"os"
)
func main() {
var foo string
if true {
foo = "foo"
} else {
foo, found := os.LookupEnv("GOPATH")
if !found {
fmt.Printf("who cares.\n")
}
}
println(foo)
}
答案 0 :(得分:5)
您使用:=
def make_combinations(x):
for a,b in itertools.combinations(x[1], 2):
yield ','.join(map(str, [a,b,1])) if a < b else ','.join(map(str, [b,a,1]))
块中创建新变量foo
if
正确的code:
foo, found := os.LookupEnv("GOPATH")
答案 1 :(得分:2)
来自Go文档:
块中声明的标识符可以在内部块中重新声明。 虽然内部声明的标识符在范围内,但它表示 内部声明声明的实体。
:=在else block redeclares foo中,所以foo现在引用一个具有相同名称的全新变量,一个从未使用过的变量。即使我们以某种方式到达了else块,最后一行的println(foo)也不会打印我们的$ GOPATH,因为它存储在另一个foo变量中(或直到整个变量超出范围)
正确的代码是:
func main() {
var foo string
if true {
foo = "foo"
} else {
var found bool
foo, found = os.LookupEnv("GOPATH")
if !found {
fmt.Printf("who cares.\n")
}
}
println(foo)
}
很容易混淆,因为这个代码工作正常,即使foo在使用之前重新声明:
func main() {
var foo string
foo = "foo"
foo, found := os.LookupEnv("GOPATH")
if !found {
fmt.Printf("who cares.\n")
}
println(foo)
}
这里发生的事情是,Go中还有另一种不同的法律重新声明:
与常规变量声明不同,是一个简短的变量声明 可以重新声明变量,只要它们最初是在之前声明的 在同一个块中(如果块是函数,则参数列出) body)具有相同的类型,以及至少一个非空白变量 是新的。因此,重新声明只能出现在 多变量简短声明。 重新声明不会引入 新变量;它只是为原始版本赋予了一个新值。
所以在其他类型的重新声明中,实际上没有创建新的foo变量,它就像赋予foo一样。