英文:
When defer func evaluates its parameters
问题
我正在学习在Go语言中如何使用defer来处理函数返回时的错误。以下是你提供的代码:
package main
import "fmt"
import "errors"
func main() {
a()
}
func a() {
var err error
defer func(){
if err != nil {
fmt.Printf("1st defer: %s\n", err)
} else {
fmt.Println("1st defer: defer not error")
}
}()
defer func(err error){
if err != nil {
fmt.Printf("2nd defer: %s\n", err)
} else {
fmt.Println("2nd defer: defer not error")
}
}(err)
err = errors.New("new error")
if err != nil {
return
}
}
输出结果为:
2nd defer: defer not error
1st defer: new error
文档中提到,参数在defer调用时被评估,这似乎应该是一致的。为什么第二个defer对变量err
有不同的值,从而产生不同的输出呢?我知道这与第二个函数将err
作为输入参数有关,但不知道具体原因。
英文:
I am learning how defer behaves in golang, and want to use it to handle error when the function returns.
Code is as below:
package main
import "fmt"
import "errors"
func main() {
a()
}
func a() {
var err error
defer func(){
if err != nil {
fmt.Printf("1st defer: %s\n", err)
} else {
fmt.Println("1st defer: defer not error")
}
}()
defer func(err error){
if err != nil {
fmt.Printf("2nd defer: %s\n", err)
} else {
fmt.Println("2nd defer: defer not error")
}
}(err)
err = errors.New("new error")
if err != nil {
return
}
}
The output:
2nd defer: defer not error
1st defer: new error
Doc says parameters are evaluated when the defer call is evaluated, which seems it should be consistent. Why 2 defer has different value for variable err
and thusly different output? I know it is related to 2nd function has err
as input parameter, but don't know why.
答案1
得分: 25
好的,以下是翻译好的内容:
好的,我刚刚弄明白了。如果你将任何参数传递给延迟函数(就像上面的第二个延迟函数),这些参数在延迟函数被延迟时进行求值,而不是在它们被执行时。这意味着在我的例子中,err
仍然是 nil
,还没有被赋值为一个新的错误。
另一方面,在上面的第一个延迟中,err
不是一个参数,而是函数 a
中的一个变量,当第一个延迟被执行时,它已经被赋值为一个新的错误。
英文:
Ok I just figured out. If you pass any parameters to the defer func (like the 2nd defer function above), those parameters are evaluated when the defer function is deferred, not when they are executed. That means in my example err
is still nil
and has not been assigned to a new error yet.
on the other hand, in 1st defer above, err
is not a parameter, but a variable in function a
, and when 1st defer is executed, it has already been assigned to a new error.
答案2
得分: 8
另一种方法是使用对原始 err 变量的引用。
package main
import (
"errors"
"fmt"
)
func main() {
a()
}
func a() {
var err error
defer func() {
if err != nil {
fmt.Printf("1st defer: %s\n", err)
} else {
fmt.Println("1st defer: defer not error")
}
}()
defer func(err *error) {
if *err != nil {
fmt.Printf("2nd defer: %s\n", *err)
} else {
fmt.Println("2nd defer: defer not error")
}
}(&err)
err = errors.New("new error")
if err != nil {
return
}
}
输出结果为:
2nd defer: new error
1st defer: new error
英文:
Another way is by using reference to original err variable
package main
import (
"errors"
"fmt"
)
func main() {
a()
}
func a() {
var err error
defer func() {
if err != nil {
fmt.Printf("1st defer: %s\n", err)
} else {
fmt.Println("1st defer: defer not error")
}
}()
defer func(err *error) {
if *err != nil {
fmt.Printf("2nd defer: %s\n", *err)
} else {
fmt.Println("2nd defer: defer not error")
}
}(&err)
err = errors.New("new error")
if err != nil {
return
}
}
And output is:
2nd defer: new error
1st defer: new error
答案3
得分: 7
以下是翻译好的内容:
在Defer语句
和Defer函数
的情况下,还有另一种类似的情况。请看下面的示例:
package main
import (
"fmt"
"time"
)
func main() {
start := time.Now()
time.Sleep(3*time.Second)
defer func() { fmt.Println("Defer函数执行时间:", time.Since(start)) }() //Defer函数
defer fmt.Println("Defer语句执行时间:", time.Since(start)) //Defer语句
time.Sleep(3*time.Second)
}
输出:
Defer语句执行时间: 3s
Defer函数执行时间: 6s
在go play中尝试上述代码。
这是因为在Defer语句
的情况下,延迟调用的参数会立即求值。
参考文档
英文:
There is another similar situation there is in case of Defer Statement
and Defer Function
. Please have look at the example below
package main
import (
"fmt"
"time"
)
func main() {
start := time.Now()
time.Sleep(3*time.Second)
defer func() { fmt.Println("Defer Function Elapsed Time: ", time.Since(start)) }() //Defer Function
defer fmt.Println("Defer Statement Elapsed Time: ", time.Since(start)) //Defer Statement
time.Sleep(3*time.Second)
}
Output:
> Defer Statement Elapsed Time: 3s
>
> Defer Function Elapsed Time: 6s
Try above in go play
This is because of in the Deferred Statement
case the deferred call's arguments are evaluated immediately
refer doc
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论