在这里我声明了一个延迟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
但是,当我推迟使用另一个annoymouse函数时,情况发生了变化
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
有人可以帮我吗!谢谢
答案 0 :(得分:1)
这是因为defer
语句仅defer
条被评估的函数调用-并且在执行defer
时对函数调用进行评估。根据文档:
每次执行“ defer”语句时,都会照常评估调用的函数值和参数并重新保存,但不会调用实际函数。取而代之的是,在周围的函数返回之前,立即按照延迟的相反顺序调用延迟的函数。也就是说,如果周围的函数通过显式的return语句返回,则在该return语句设置任何结果参数之后但在函数返回其调用者之前,将执行延迟的函数。如果延迟的函数值计算为nil,则在调用该函数时执行恐慌,而不是在执行“ defer”语句时恐慌。
您的代码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))
}
}
答案 1 :(得分:0)
使用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 ....
}()