Here’s a small quiz derived from some incorrect advice from an AI coding assistant.
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now())
defer fmt.Println(time.Now())
time.Sleep(10 * time.Second)
}
This program prints two timestamps; will they be
a. Roughly the same time (ie, the same second)
b. Roughly 10 seconds apart
c. Something else
Answer after the fold
The answer is a, the timestamps will be approximately the same (modulo the tiny amount of time between two sequential calls to time.Now() ). But why?
In Go, the arguments to any function are evaluated before the function is called. When applied to defer statements, the second time.Now() is evaluated immediately, then printed after the delay.
To cause the time.Now() evaluation to be deferred until the defer block runs, this syntax should be used
defer func() { fmt.Println(time.Now()) }()
This is a trivial example, but a more common occurrence of this bug can show up in logging and metrics collection, for example
func ServeHTTP(rw http.ResponseWriter, req *http.Request) {
fmt.Println("request started at", time.Now())
defer fmt.Println("request completed at", time.Now())
// handle request
}