Go中的短变量声明和长变量声明之间的闭包范围有什么区别?

From my reading of the spec:

A short variable declaration ... is a shorthand for a regular variable declaration with initializer expressions but no types...

http://golang.org/ref/spec

I would have thought the two were identical:

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

and

f := func() {
    ...
}

But it seems like they're not. I was trying to wrap a self-recursive function inside of an outer function, but this works:

func myOuter() {
    var f func()

    f = func() {
        f()
    }

    f()
}

But this doesn't, saying undefined: f in the inner function.

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

    f()
}

So what is the difference? Is there any way to write this with the short-form declaration or I do I have to write it out long-hand?

f := func() { /* ... */ } is identical to var f func() = func() { /* ... */ } (but only the later one is allowed at the package level). In your specific case, neither of the two variants will work, since the statement will be evaluated from right to left. The solution is - as you have already suggested - to split the statement into two. One for declaring the variable and another for assigning the recursive function to it.

Your first two code samples are semantically identical under one condition: the expression that is being assigned to your variable needs to resolve at compile time.

This will be identical in every circumstance except when you are trying to assign an expression that referencees the variable (or function) you just declared. The issue here is that because golang is parsed right-associatively, it will try to type resolve the expression on the right before assigning it to the left. If you reference the variable on the the left of the declare-assign operator, you are referencing a variable that the compiler does not yet have knowledge of, hence the undefined: f.

Another example that would yield similar results:

x := x + 1

Though this is far less common for people to attempt since it is more obvious that x has not yet been assigned.