Go中的短变量声明和长变量声明之间的闭包范围差异是什么?

时间:2012-07-08 11:39:19

标签: recursion closures go

从我阅读规范:

  

短变量声明...是常规变量的简写   声明与初始化表达式但没有类型......

http://golang.org/ref/spec

我原以为这两者是相同的:

var f func()
f = func() {
    ...
}

f := func() {
    ...
}

但似乎他们不是。我试图在外部函数中包含一个自递归函数,但这有效:

func myOuter() {
    var f func()

    f = func() {
        f()
    }

    f()
}

但这不是,在内部函数中说undefined: f

func myOuter() {
    f := func() {
        f()
    }

    f()
}

那有什么区别? 有没有办法用简短的声明来写这个,或者我必须用长手写出来吗?

2 个答案:

答案 0 :(得分:14)

f := func() { /* ... */ }var f func() = func() { /* ... */ }相同(但在包级别只允许后一个)。在您的特定情况下,这两个变体都不起作用,因为语句将从右到左进行评估。正如您已经建议的那样,解决方案是将语句拆分为两个。一个用于声明变量,另一个用于为其分配递归函数。

答案 1 :(得分:0)

前两个代码示例在一个条件下语义相同:分配给变量的表达式需要在编译时解析。

除非您尝试分配引用刚刚声明的变量(或函数)的表达式,否则在每种情况下都是相同的。这里的问题是因为golang是以右关联方式解析的,所以在将其分配给左边之前,它会尝试键入解析右边的表达式。如果引用declare-assign运算符左侧的变量,则引用编译器尚不知道的变量,因此undefined: f

另一个产生类似结果的例子:

x := x + 1

虽然人们尝试这种情况的情况要少得多,因为更明显的是x还没有被分配。