我正在学习delang中的延迟行为,并希望在函数返回时使用它来处理错误。
代码如下:
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
Doc表示在评估延迟调用时会评估参数,这似乎应该是一致的。为什么2 defer对变量err
有不同的值,因此输出不同?我知道它与第二个函数有err
作为输入参数,但不知道为什么。
答案 0 :(得分:7)
好的,我刚想通了。如果将任何参数传递给延迟函数(如上面的第二个延迟函数),则延迟延迟函数时评估这些参数,而不是在执行它们时。这意味着在我的示例中err
仍然是nil
,尚未分配给新错误。
另一方面,在上面的第一个延迟中,err
不是参数,而是函数a
中的变量,并且当执行第一个延迟时,它已被分配给新的错误
答案 1 :(得分:2)
另一种方法是使用对原始 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
答案 2 :(得分:1)
在Defer Statement
和Defer Function
的情况下,还有另一种类似的情况。请看下面的例子
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)
}
输出:
延迟陈述经过时间:3秒
延迟功能经过的时间:6s
在go play上尝试以上
这是因为在Deferred Statement
情况下,立即评估了延迟调用的参数
refer doc