英文:
Why defer behaves differently with variables defined in the surrounding function than named results?
问题
下面的程序返回:
<nil>
hello
我期望两者都返回"hello",但事实并非如此。我在语言规范的示例中找到了这种行为的说明。
例如,如果延迟函数是一个函数字面量,并且周围的函数具有在字面量内部范围内的命名结果参数,则延迟函数可以在返回之前访问和修改结果参数。
我的问题是:为什么延迟函数在处理周围函数中定义的变量时与命名结果不同?它不只是在周围函数返回之前执行的闭包吗?
package main
import (
"errors"
"fmt"
)
func main() {
fmt.Println(up())
fmt.Println(up2())
}
func up() error {
var err error
defer func() {
err = errors.New("hello")
}()
return err
}
func up2() (err error) {
defer func() {
err = errors.New("hello")
}()
return err
}
func up3() error {
var err error
fn := func() {
err = errors.New("hello")
}
fn()
return err
}
英文:
The program below returns
<nil>
hello
I expected both to return "hello" but it's not the case. I've found that the behaviour is given as example in the language spec.
> For instance, if the deferred function is a function literal and the surrounding function has named result parameters that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned.
My question is: why does defer works differently with variables defined in the surrounding function than with named results? Isn't it just a closure executed before the surrounding function returns?
package main
import (
"errors"
"fmt"
)
func main() {
fmt.Println(up())
fmt.Println(up2())
}
func up() error {
var err error
defer func() {
err = errors.New("hello")
}()
return err
}
func up2() (err error) {
defer func() {
err = errors.New("hello")
}()
return err
}
func up3() error {
var err error
fn := func() {
err = errors.New("hello")
}
fn()
return err
}
答案1
得分: 5
规范中提到:
> "defer"语句会调用一个函数,该函数的执行被延迟到包围它的函数返回的时刻,无论是因为包围它的函数执行了一个return语句,到达了函数体的末尾,还是因为相应的goroutine正在发生panic。
一个关键点是,延迟函数在return语句执行之后执行。
规范还提到:
> 函数F中的"return"语句终止了F的执行,并可选择提供一个或多个结果值。F延迟的任何函数都会在F返回给其调用者之前执行。
函数up
返回nil,因为延迟函数在return语句提供函数结果之后设置了err
。
函数up2
覆盖了return语句设置的结果值。
英文:
The spec says:
> A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.
A key point is that the deferred function is executed after the return statement is executed.
The spec also says:
> A "return" statement in a function F terminates the execution of F, and optionally provides one or more result values. Any functions deferred by F are executed before F returns to its caller.
The function up
returns nil because the deferred function sets err
after the return statement provides the function result.
The function up2
overwrites the result value set by the return statement.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论