英文:
Measure elapsed time with a defer statement in Go
问题
我考虑使用defer
语句来测量Go程序的运行时间:
func main() {
start := time.Now()
defer fmt.Println(fmt.Sprintf("The process took %s", time.Now().Sub(start)))
...
}
我以为这样会得到正确的结果,但实际上并没有:
[09:36:55]pc@work:~/test$ go run ./main.go
Processed 209806/209806 TUF files
All records are inserted in the database.
Verifying records are inserted correctly...
Verified 209806/209806 TUF files
All records have been inserted and verified successfully.
The process took 600ns
[14:24:06]pc@work:~/test$
尽管整个过程花费了5个小时,这可以从左侧的时间戳看出,但延迟执行的fmt.Println()
语句显示了600纳秒。我做错了什么?
英文:
I thought of using the defer
statement to measure the elapsed time of a program in Go:
func main() {
start := time.Now()
defer fmt.Println(fmt.Sprintf("The process took %s", time.Now().Sub(start)))
...
}
I thought this would produce the correct result but it didn't:
[09:36:55]pc@work:~/test$ go run ./main.go
Processed 209806/209806 TUF files
All records are inserted in the database.
Verifying records are inserted correctly...
Verified 209806/209806 TUF files
All records have been inserted and verified successfully.
The process took 600ns
[14:24:06]pc@work:~/test$
Even though the process took 5 hours, which is visible from the timestamps on the left, the deferred fmt.Println()
statement showed 600 nanoseconds. What am I doing wrong?
答案1
得分: 4
延迟函数参数会立即进行评估。你可以将它们的评估包装在一个匿名函数中,以延迟它们的评估,直到实际触发延迟操作:
defer func() {
fmt.Println(fmt.Sprintf("The process took %s", time.Now().Sub(start)))
}()
在A Tour of Go和语言规范中了解更多关于延迟语句的信息。
英文:
Defered function arguments are evaluated immediately. You can wrap their evaluation into an anonymous function to delay their evaluation until the defer actually gets triggered:
defer func() {
fmt.Println(fmt.Sprintf("The process took %s", time.Now().Sub(start)))
}()
Read more about the defer statement in A Tour of Go and the language specification.
答案2
得分: 3
defer
关键字后面的函数参数会立即被求值,这意味着time.Now().Sub(start)
部分会在start
之后立即计算。
如果你想计时函数的执行时间,可以这样写:
defer func() {
time.Now().Sub(start) // ...
}()
另外,我写了一个包来实现这个功能:https://github.com/gonutz/tic,你可以这样使用:
func main() {
defer tic.Toc()()
}
注意到代码中的两个()()
,它们的作用是完全相同的,第一个函数调用开始计时并返回一个被延迟执行的函数,该函数用于停止计时。
英文:
The arguments to the defer
red function are evaluated right away, meaning the time.Now().Sub(start)
part is computed right after the start.
If you want to time the function, say:
defer func() {
time.Now().Sub(start) // ...
}()
Alternatively, I have written a package for it: https://github.com/gonutz/tic so you can say:
func main() {
defer tic.Toc()()
}
and note the two ()()
which are there for the exact same reason, the first function call starts the timing and returns a function to be deferred which stops the timing.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论