为什么当 annoymouse 函数返回时 defer 语句的工作方式不同
why defer statement works differently when annoymouse function returned
这里我声明了一个延迟trace1的函数
func TestDeferFunc(t *testing.T) {
fmt.Println("start", time.Now())
defer trace1()
time.Sleep(3 * time.Second)
}
func trace1() {
startTime := time.Now()
fmt.Println("end time: ", startTime)
fmt.Println("execute time: ", time.Since(startTime))
}
在 运行 go test -run=^TestDeferFunc$
之后,下面是我得到的
start 2019-11-26 12:50:59.59489797 +0800 CST m=+0.000202866
end time: 2019-11-26 12:51:02.595090951 +0800 CST m=+3.000395880
execute time: 49.065µs
然而,当我推迟另一个烦人的功能时,事情发生了变化
func TestDeferFunc(t *testing.T) {
fmt.Println("start", time.Now())
defer trace2()()
time.Sleep(3 * time.Second)
}
func trace2() func() {
startTime := time.Now()
fmt.Println("end time: ", startTime)
fmt.Println("execute time: ", time.Since(startTime))
return func() {
fmt.Println("zzz")
}
}
下面是 go test
结果
start 2019-11-26 12:52:58.318472958 +0800 CST m=+0.000197852
end time: 2019-11-26 12:52:58.318554368 +0800 CST m=+0.000279262
execute time: 4.853µs
zzz
有人能帮帮我吗!谢谢
这是因为 defer
语句仅 defer
评估函数调用 - 并且函数调用在 defer
执行时评估。根据文档:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred. That is, if the surrounding function returns through an explicit return statement, deferred functions are executed after any result parameters are set by that return statement but before the function returns to its caller. If a deferred function value evaluates to nil, execution panics when the function is invoked, not when the "defer" statement is executed.
您的代码 defer trace2()()
本质上等同于 f := trace2(); defer f()
。所以 trace2
立即被评估(并因此被调用)。
因此,为了实现您可能想要的(跟踪时间),您可以像这样使用 defer trace3()()
和 trace3()
:
func trace3() func() {
startTime := time.Now()
return func() {
fmt.Println("end time: ", time.Now())
fmt.Println("execute time: ", time.Since(startTime))
}
}
使用 defer 跟踪时间的方法是将开始时间传递给 deferred 函数:
func trace1(startTime time.Time) {
fmt.Println("start", startTime)
fmt.Println("end time: ", time.Now())
fmt.Println("execute time: ", time.Since(startTime))
}
func TestDeferFunc(t *testing.T) {
defer trace1(time.Now())
time.Sleep(3 * time.Second)
}
传入的参数立即执行,但真正的函数调用延迟到最后。
如果您想更明确地了解执行的内容和延迟的内容,您可以将整个事情包装在一个函数中,这样您就可以确保内部的所有内容都在最后执行
defer func() {
..... code ....
}()
这里我声明了一个延迟trace1的函数
func TestDeferFunc(t *testing.T) {
fmt.Println("start", time.Now())
defer trace1()
time.Sleep(3 * time.Second)
}
func trace1() {
startTime := time.Now()
fmt.Println("end time: ", startTime)
fmt.Println("execute time: ", time.Since(startTime))
}
在 运行 go test -run=^TestDeferFunc$
之后,下面是我得到的
start 2019-11-26 12:50:59.59489797 +0800 CST m=+0.000202866
end time: 2019-11-26 12:51:02.595090951 +0800 CST m=+3.000395880
execute time: 49.065µs
然而,当我推迟另一个烦人的功能时,事情发生了变化
func TestDeferFunc(t *testing.T) {
fmt.Println("start", time.Now())
defer trace2()()
time.Sleep(3 * time.Second)
}
func trace2() func() {
startTime := time.Now()
fmt.Println("end time: ", startTime)
fmt.Println("execute time: ", time.Since(startTime))
return func() {
fmt.Println("zzz")
}
}
下面是 go test
结果
start 2019-11-26 12:52:58.318472958 +0800 CST m=+0.000197852
end time: 2019-11-26 12:52:58.318554368 +0800 CST m=+0.000279262
execute time: 4.853µs
zzz
有人能帮帮我吗!谢谢
这是因为 defer
语句仅 defer
评估函数调用 - 并且函数调用在 defer
执行时评估。根据文档:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred. That is, if the surrounding function returns through an explicit return statement, deferred functions are executed after any result parameters are set by that return statement but before the function returns to its caller. If a deferred function value evaluates to nil, execution panics when the function is invoked, not when the "defer" statement is executed.
您的代码 defer trace2()()
本质上等同于 f := trace2(); defer f()
。所以 trace2
立即被评估(并因此被调用)。
因此,为了实现您可能想要的(跟踪时间),您可以像这样使用 defer trace3()()
和 trace3()
:
func trace3() func() {
startTime := time.Now()
return func() {
fmt.Println("end time: ", time.Now())
fmt.Println("execute time: ", time.Since(startTime))
}
}
使用 defer 跟踪时间的方法是将开始时间传递给 deferred 函数:
func trace1(startTime time.Time) {
fmt.Println("start", startTime)
fmt.Println("end time: ", time.Now())
fmt.Println("execute time: ", time.Since(startTime))
}
func TestDeferFunc(t *testing.T) {
defer trace1(time.Now())
time.Sleep(3 * time.Second)
}
传入的参数立即执行,但真正的函数调用延迟到最后。
如果您想更明确地了解执行的内容和延迟的内容,您可以将整个事情包装在一个函数中,这样您就可以确保内部的所有内容都在最后执行
defer func() {
..... code ....
}()