Defer Order
defer schedules a call to run when the surrounding function returns, no matter
which return it takes or whether it panics on the way out:
func read() {
f := open("data.txt")
defer close(f)
// ... close(f) runs here, whatever happens above
}
Two rules explain everything defer does.
Deferred calls run last-in, first-out. They go on a stack, so the last one you defer is the first one to run. That is what you want: you release things in the reverse of the order you acquired them.
The arguments are evaluated at the defer statement, not when the call
runs. defer fmt.Println(n) snapshots n immediately. A deferred closure
that reads n in its body is the opposite: it sees whatever n holds at
return time.
Because deferred functions run after the return value has been set, a closure over a named result can still change it, and the caller sees the change.
Task
Fill in the five functions in main.go.
LIFO(labels []string) (order []string)defers one appending call per label and returns the order they ran in, soa, b, ccomes back asc, b, a.Steps() (log []string)logsenter, deferscleanup-1thencleanup-2, logswork, and returns[enter work cleanup-2 cleanup-1].CapturedValue() (recorded int)passesnto the deferred function as an argument before changingn, and returns what was recorded.CapturedVariable() (recorded int)is the same, except the deferred function closes overninstead.DoubleResult(n int) (result int)returnsndoubled, with the doubling done by a deferred function.
Hints
- These functions all have named results. A bare
returnsets them to what they currently hold and then runs the defers, which can still change them. defer f()callsfnow and defers whatever it returned. To defer a block of work, defer a function literal:defer func() { ... }(), trailing()included.LIFOneeds no reversing logic and no counter. Defer inside the loop and let the stack do it.- The difference between 3 and 4 is one line of syntax:
func(seen int) { ... }(n)freezesn,func() { ... }()does not. DoubleResultcannot double before thereturn; the test would still pass, but the point is that the deferred call editsresultafter it is set.