当 defer func 评估其参数时
When defer func evaluates its parameters
我正在学习 defer 在 golang 中的行为方式,并希望在函数 returns.
时使用它来处理错误
代码如下:
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说参数是在defer调用求值的时候求值的,看来应该是一致的。为什么 2 defer 对变量 err
有不同的值,因此输出不同?我知道它与第二个函数有关 err
作为输入参数,但不知道为什么。
好的,我刚刚明白了。如果您将任何参数传递给延迟函数(如上面的第二个延迟函数),这些参数在延迟函数被延迟时计算,而不是在它们被执行时计算。这意味着在我的示例中 err
仍然是 nil
并且尚未分配给新错误。
另一方面,在上面的第一个defer中,err
不是参数,而是函数a
中的一个变量,当第一个defer执行时,它已经被赋值给了一个新错误。
另一种方法是使用对原始 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
在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)
}
输出:
Defer Statement Elapsed Time: 3s
Defer Function Elapsed Time: 6s
在 go play
中尝试上面的方法
这是因为在 Deferred Statement
的情况下,延迟调用的参数会立即计算
refer doc
我正在学习 defer 在 golang 中的行为方式,并希望在函数 returns.
时使用它来处理错误代码如下:
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说参数是在defer调用求值的时候求值的,看来应该是一致的。为什么 2 defer 对变量 err
有不同的值,因此输出不同?我知道它与第二个函数有关 err
作为输入参数,但不知道为什么。
好的,我刚刚明白了。如果您将任何参数传递给延迟函数(如上面的第二个延迟函数),这些参数在延迟函数被延迟时计算,而不是在它们被执行时计算。这意味着在我的示例中 err
仍然是 nil
并且尚未分配给新错误。
另一方面,在上面的第一个defer中,err
不是参数,而是函数a
中的一个变量,当第一个defer执行时,它已经被赋值给了一个新错误。
另一种方法是使用对原始 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
在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)
}
输出:
Defer Statement Elapsed Time: 3s
Defer Function Elapsed Time: 6s
在 go play
中尝试上面的方法这是因为在 Deferred Statement
的情况下,延迟调用的参数会立即计算
refer doc