Go

What do f(), g(), and h() return?

Question 482HardGo 1.22 to 1.25
func f() (r int) {
    defer func() { r *= 2 }()
    return 3
}

func g() int {
    r := 3
    defer func() { r *= 2 }()
    return r
}

func h() (r int) {
    defer func() { r *= 2 }()
    r = 1
    return r + 10
}

f() returns 6, g() returns 3, and h() returns 22.

return X is not atomic. It first assigns X to the result parameter, then runs the deferred functions, then returns. With a named result, a deferred closure can read and change that result after the assignment. In f, r becomes 3 and then 6. In h, r becomes 11 and then 22.

In g the result is unnamed. The closure changes the local r, but the return value was already copied into an unnamed result slot, so the caller gets 3.

This is the mechanism behind the common idiom defer func() { if err != nil { err = fmt.Errorf("op: %w", err) } }() and behind turning a recovered panic into a returned error. The interviewer wants the three-step explanation.

More on Tricky Output & Code-Review Puzzles

All 38 Tricky Output & Code-Review Puzzles questions