has a , which “defers” the execution of a function until the surrounding returns. Multiple _defer_s are stacked so that the most recently _defer_red function is run first. Golang keyword defer function last-in first-out 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 in other languages? keyword finally From , Java Docs 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. finally Well, let’s compare to the following example using . defer Java 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”: separates alike concerns. Because you can’t declare that you’d like to close a file when you open it, you can’t effectively plan ahead; instead, you have to remember to fit it into the surrounding context. I can’t count how many programmer errors I’ve seen due to separating alike concerns. Separation of similar concerns. finally requires immediate, exclusive, and interrupting attention, whereas allows you to plan ahead without interrupting your usual control flow. In the Go example, we could easily defer incrementing a metric as we read each line, whereas in Java, deferring multiple calls would require more advanced control flow, like a queue, so instead, we have to our flow by aggregating. Interruptions. finally defer reorganize enforces nesting, which hurts overall readability, whereas can be dropped in inline. Notice the check, counters, and separate definition from declaration. Holistically, none of these characteristics are meaningful to a reader, but they’re forced to parse it due to the nested structure. Readability. finally defer != null This may not be a point you were expecting to flow to Go’s side, but altogether, is more declarative. You tell the computer that you want to X, Y, Z rather than . Imperative vs. Declarative. defer do how Alike most technical debt, I’ve found that each of these “gotchas” becomes more apparent as the complexity of your function grows. Conclusion Though unconventional, Go’s is pure brilliance. It disguises a generally complex control flow with a simple, universal one that both helps readability and keeps things declarative ( ). It’s far superior to traditional teardown via , and you should almost always prefer it to rolling out your own control flow. defer two factors that are not mutually inclusive finally If you found this interesting, consider following me on , where I share my experiences with Go amongst other things. Twitter is how hackers start their afternoons. We’re a part of the family. We are now and happy to opportunities. Hacker Noon @AMI accepting submissions discuss advertising &sponsorship To learn more, , , or simply, read our about page like/message us on Facebook tweet/DM @HackerNoon. If you enjoyed this story, we recommend reading our and . Until next time, don’t take the realities of the world for granted! latest tech stories trending tech stories