Golang has a defer keyword, which “defers” the execution of a function until the surrounding function returns. Multiple _defer_s are stacked last-in first-out so that the most recently _defer_red function is run first.
Let’s check out an example of this in practice.
func writeLogs(c chan []string) {defer stats.Duration("write_logs_fn", time.Now()) // order: 4
file, err := os.Create("request.log", filename)if err != nil {panic(err)}defer file.Close() // order: 3
writer := csv.NewWriter(file)defer writer.Flush() // order: 2
for line := range c {err := writer.Write(line)if err != nil {panic(err)}defer stats.Increment("wrote_line") // order: 1}}
At first glance, you may ask —
How is this different from the finally keyword in other languages?
From Java Docs,
finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.
Well, let’s compare defer to the following Java example using finally.
static void writeLogs(List<List<String>> lines) throws Exception {Date start = new Date();FileWriter writer = null;int lineCount = 0;
try {writer = new FileWriter("request.log");// non-buffered inputfor (int i = 0; i < lines.size(); i++) {// naive CSV writerfor (value : lines[i]) {writer.append(value);writer.append(",");}writer.append("\n");lineCount++;}} finally {if (writer != null) {writer.flush();writer.close();}
**stats.increment("wrote\_line", lineCount);
stats.duration(start);
}**}
Off the bat, you can identify a handful of “gotchas”:
Alike most technical debt, I’ve found that each of these “gotchas” becomes more apparent as the complexity of your function grows.
Though unconventional, Go’s defer is pure brilliance. It disguises a generally complex control flow with a simple, universal one that both helps readability and keeps things declarative (two factors that are not mutually inclusive). It’s far superior to traditional teardown via finally, and you should almost always prefer it to rolling out your own control flow.
If you found this interesting, consider following me on Twitter, where I share my experiences with Go amongst other things.
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising &sponsorship opportunities.
To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!