oinume journal

Scratchpad of what I learned

Arguments to defered functions are evaluated when the defer executes

The arguments to the deferred function (which include the receiver if the function is a method) are evaluated when the defer executes, not when the call executes.

Effective Go - The Go Programming Language

I sometimes make a mistake that defered functions are evaluated when the function is called but it’s wrong. Here is an example.

package main

import (
        "fmt"
        "time"
)

type wrapped func()

func main() {
        wrapper(func () {
                time.Sleep(time.Second * 3)
                fmt.Println("Hello")
        })
}

func wrapper(f wrapped) {
        fmt.Println("wrapper() start: ", time.Now().UTC())
        defer instrument(time.Now().UTC())
        f()
        fmt.Println("wrapper()   end: ", time.Now().UTC())
}

func instrument(start time.Time) {
        fmt.Println("instrument():    ", start)
}
$ go run defer.go
wrapper() start:  2016-05-23 07:28:37.474091714 +0000 UTC
Hello
wrapper()   end:  2016-05-23 07:28:40.474272645 +0000 UTC
instrument():     2016-05-23 07:28:37.474139821 +0000 UTC

If defer functions are evaluated at call time, instrument() time must be 3 seconds later.