英文:
What's the closure scoping difference between short variable declarations and long ones in Go?
问题
根据规范的阅读:
> 短变量声明...是对带有初始化表达式但没有类型的常规变量声明的简写...
我本以为这两者是相同的:
var f func()
f = func() {
...
}
和
f := func() {
...
}
但它们似乎并不相同。我试图在外部函数中包装一个自递归函数,但这个可以工作:
func myOuter() {
var f func()
f = func() {
f()
}
f()
}
但这个不行,在内部函数中会显示“undefined: f”。
func myOuter() {
f := func() {
f()
}
f()
}
那么有什么区别呢?
有没有办法用简写声明来编写这个,还是我必须手动编写它?
英文:
From my reading of the spec:
> A short variable declaration ... is a shorthand for a regular variable
> declaration with initializer expressions but no types...
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?
答案1
得分: 14
f := func() { /* ... */ }
与var f func() = func() { /* ... */ }
是相同的(但只有后者允许在包级别)。在您的特定情况下,这两种变体都不起作用,因为语句将从右到左进行评估。解决方案是-如您已经建议的-将语句拆分为两个部分。一个用于声明变量,另一个用于将递归函数分配给它。
英文:
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.
答案2
得分: 0
你的前两个代码示例在一个条件下是语义上相同的:被赋值给变量的表达式需要在编译时解析。
除非你尝试给刚刚声明的变量(或函数)赋值一个引用该变量的表达式,否则在任何情况下都是相同的。问题在于,由于golang是从右向左解析的,它会在将表达式赋值给左边之前尝试对右边的表达式进行类型解析。如果你在声明-赋值运算符的左边引用了变量,那么你引用的是编译器尚未知道的变量,因此会出现undefined: f
的错误。
另一个会产生类似结果的示例:
x := x + 1
尽管这种情况较少见,因为很明显x尚未被赋值。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论