DEV Community

Bryan Sazon
Bryan Sazon

Posted on

Golang: Defer Gotchas and Hack

#go

Sample Program

package main

import "fmt"

func main() {
    p := person{"john", 15}
    defer printPerson(p)
    updateAge(&p, 20)
}

type person struct {
    name string
    age  int
}

func printPerson(p person) {
    fmt.Printf("Name: %s, Age: %d", p.name, p.age)
}

func updateAge(p *person, newAge int) {
    p.age = newAge
}

Run the program.

$ go run main.go

Name: john, Age: 15

I was expecting 20, but I got 15. This is because "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.". See effective go - defer.

This means that the time that defer printPerson(p) was called, that p is already set in stone.

Workaround

Now, put printPerson(p) under an anonymous function.


func main() {
    p := person{"john", 15}
    // defer printPerson(p)
    defer func() {
        printPerson(p)
    }()
    updateAge(&p, 20)
}

Run the program.

$ go run main.go

Name: john, Age: 20

Why? The documentation only says the arguments to the deferred function are evaluated when the defer executes. In the modified code above, that deferred function is the anonymous function, and not the function printPerson. Hack!

Top comments (0)