Oops!
It seems that Friday’s email got stuck, and didn’t actually send until late Monday. Meaning you probably got two emails in the same day, and out of order. I hope it didn’t bother anyone too much.
I should probably make a joke about how it was deferred… Nah!
Today we’ll be finishing up the section on the defer
keyword, with one special capability that it affords us.
Defer statements
…
For instance, if the deferred function is a function literal and the surrounding function has named result parameters that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned. If the deferred function has any return values, they are discarded when the function completes. (See also the section on handling panics.)
lock(l) defer unlock(l) // unlocking happens before surrounding function returns // prints 3 2 1 0 before surrounding function returns for i := 0; i <= 3; i++ { defer fmt.Print(i) } // f returns 42 func f() (result int) { defer func() { // result is accessed after it was set to 6 by the return statement result *= 7 }() return 6 }
As we can see in the example presented, a deferred function has the ability to set a named return value, before it is actually returned.
This only works for named return values. And is what allows recovery from a panic (which we’ll get to soon).
For now, the main thing I’d like to draw your attention to is the relationship, and distinction with, naked returns.
Frequently, when warning against the use of naked returns, someone will point out the benefit of being able to modify a named return value in a deferred statement as an argument in favor of naked returns.
While both of these features, modifying return values in a deferred function, and naked returns, depend on named return values. However, they are distinct features, and the use of one does not imply the use of the other.
Quotes from The Go Programming Language Specification Language version go1.23 (June 13, 2024)