在Go语言中使用defer语句来测量经过的时间。

huangapple go评论107阅读模式
英文:

Measure elapsed time with a defer statement in Go

问题

我考虑使用defer语句来测量Go程序的运行时间:

  1. func main() {
  2. start := time.Now()
  3. defer fmt.Println(fmt.Sprintf("The process took %s", time.Now().Sub(start)))
  4. ...
  5. }

我以为这样会得到正确的结果,但实际上并没有:

  1. [09:36:55]pc@work:~/test$ go run ./main.go
  2. Processed 209806/209806 TUF files
  3. All records are inserted in the database.
  4. Verifying records are inserted correctly...
  5. Verified 209806/209806 TUF files
  6. All records have been inserted and verified successfully.
  7. The process took 600ns
  8. [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:

  1. func main() {
  2. start := time.Now()
  3. defer fmt.Println(fmt.Sprintf("The process took %s", time.Now().Sub(start)))
  4. ...
  5. }

I thought this would produce the correct result but it didn't:

  1. [09:36:55]pc@work:~/test$ go run ./main.go
  2. Processed 209806/209806 TUF files
  3. All records are inserted in the database.
  4. Verifying records are inserted correctly...
  5. Verified 209806/209806 TUF files
  6. All records have been inserted and verified successfully.
  7. The process took 600ns
  8. [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

延迟函数参数会立即进行评估。你可以将它们的评估包装在一个匿名函数中,以延迟它们的评估,直到实际触发延迟操作:

  1. defer func() {
  2. fmt.Println(fmt.Sprintf("The process took %s", time.Now().Sub(start)))
  3. }()

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:

  1. defer func() {
  2. fmt.Println(fmt.Sprintf("The process took %s", time.Now().Sub(start)))
  3. }()

Read more about the defer statement in A Tour of Go and the language specification.

答案2

得分: 3

defer关键字后面的函数参数会立即被求值,这意味着time.Now().Sub(start)部分会在start之后立即计算。

如果你想计时函数的执行时间,可以这样写:

  1. defer func() {
  2. time.Now().Sub(start) // ...
  3. }()

另外,我写了一个包来实现这个功能:https://github.com/gonutz/tic,你可以这样使用:

  1. func main() {
  2. defer tic.Toc()()
  3. }

注意到代码中的两个()(),它们的作用是完全相同的,第一个函数调用开始计时并返回一个被延迟执行的函数,该函数用于停止计时。

英文:

The arguments to the deferred 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:

  1. defer func() {
  2. time.Now().Sub(start) // ...
  3. }()

Alternatively, I have written a package for it: https://github.com/gonutz/tic so you can say:

  1. func main() {
  2. defer tic.Toc()()
  3. }

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.

huangapple
  • 本文由 发表于 2022年7月13日 19:41:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/72965657.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定