Defer And Closure in Go-lang

Atharva Chidambar Joshi
4 min readApr 12, 2023

--

Hello, fellow internet user, before we begin, this article assumes you have the following pre-requisites

  • You know about functions in go
  • have an understanding of the local and global scope
  • Have your vsc setup for go-lang, because it’ll be a delightful experience with autocomplete, linting and auto-imports

With that out of the way, onto the main issue at hand, young padawan.

Just what is defer all about?

Just so we’re on the same page, you always use defer keyword on a function call. Now what defer means is that the execution of the deferred function is delayed till the end of the surrounding function.

  • In the code above, the deferred function is fmt.Println("Two") , so this function will execute once the surrounding function is done executing, in our case it was simply to print fmt.Println("Three"), once that is over the deferred function is executed.
  • One thing to note is that if you have multiple defer keywords in a single function, they will be executed in First In Out Last, or FILO order, in simple words, the reverse order in which they were deferred.
  • Let’s go a little crazy for a second and add defer keyword to everything you see, try predicting the output.
  • In the code above, since everything is deferred, nothing is executed till the control reaches line 8, as fmt.Println("Four") is the last function to be deferred, it is executed first, in other words, it doesn't make much difference if you want to defer a function just before the surrounding function ends.
  • And since fmt.Println("One") was first to be deferred, it was executed last.
  • Things to note, the deferred function belongs to the surrounding function and not the block scope, so if you deferred a function in an if block, or a for loop, the deferred function will always execute after the surrounding function ends, not before the loop or if statement.

Okay, but what if I wanted to return something from a deferred function?

  • well, you can’t do it, your function needs to be the kind that returns nothing, or you can have a return and choose to defer it but you’ll have to ignore the return value.
  • But go has this feature called named return, which makes things a little interesting.
  • In the line above, when the function is created, returnVal is 0, we're deferring the anonymous function so we jump to line 15, there returnVal becomes -1, finally, our function is fired and we overwrite returnVal as 1000 and we return that value.

Okay now for closures

  • Closures are function values that reference variables residing outside of the function in question.
  • This piece of code is shamelessly stolen from the go docs because it is actually that effective to understand.
  • things to note: despite having sum defined outside the scope of the anonymous return function, thesum variable is tied along with it, with a different copy every time adder() is called to be precise.
  • here since each instance of the anonymous function, which happens to be pos(i int) and neg(i int) , can be called with a different parameter, they both have their own sum variable under the hood, which allows them to have different outputs as shown.

let’s mix things up!!

  • it gets more interesting when you defer an anonymous function in a loop, as the function loses its meaning outside the scope of the loop, the compiler has to keep track of the deferred function calls in different ways, have a look below.
  • here vsc shows that the variable index will be captured, that is to say, the address space index is referring will be tied to the function, that is why in the output, we see that captured index is 4 is printed 4 times, this is due to the closure concept.
  • but in the other loop, in line 17, we store the value that index holds along with the function, as dictated by the docs here,

Each time a “defer” statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.

Hope you learned something from this article, if there are any incorrect assumptions made on my behalf, please do tell :), nothing would delight me more than dispelling my inaccurate understandings.

Meanwhile, I’ll just link the things that helped me write this article

Thanks for reading and hope you have a great day 😁

Originally published at https://toothsy.hashnode.dev.

--

--