Deferred Code

Suppose you have a function in which you open a file and perform various writesand reads on it. In such a function there are often spots where you want toreturn early. If you do that, you will need to close the file descriptor you areworking on. This often leads to the following code:

  1. func ReadWrite() bool {
  2. file.Open("file")
  3. // Do your thing
  4. if failureX {
  5. file.Close() 1
  6. return false
  7. }
  8. if failureY {
  9. file.Close() 1
  10. return false
  11. }
  12. file.Close() 1
  13. return true 2
  14. }

Note that we repeat a lot of code here; you can see the that file.Close() iscalled at 1. To overcome this, Go has the defer keyword. After defer you specify a function which is called just _before_2the current function exits.

With defer we can rewrite the above code as follows. It makes the functionmore readable and it puts the Close right next to the Open.

  1. func ReadWrite() bool {
  2. file.Open("filename")
  3. defer file.Close() 1
  4. // Do your thing
  5. if failureX {
  6. return false 2
  7. }
  8. if failureY {
  9. return false 2
  10. }
  11. return true 2
  12. }

At 1 file.Close() is added to the defer list. Close is now done automatically at 2. This makes the function shorter andmore readable. It puts the Close right next to the Open.

You can put multiple functions on the “defer list”, like this example from

  1. for i := 0; i < 5; i++ {
  2. defer fmt.Printf("%d ", i)
  3. }

Deferred functions are executed in LIFO order, so the above code prints: 43 2 1 0.

With defer you can even change return values, provided that you are usingnamed result parameters and a function literal 9, i.e:

  1. defer func() {/* ... */}()

Here we use a function without a name and specify the body of the functioninline, basically we’re creating a nameless function on the spot. The finalbraces are needed because defer needs a function call, not a function value.If our anonymous function would take an parameter it would be easier to see whywe need the braces:

  1. defer func(x int) {/* ... */}(5)

In this (unnamed) function you can access any named return parameter:

  1. func f() (ret int)
  2. defer func() { 1
  3. ret++
  4. }()
  5. return 0
  6. }

Here 1 we specify our function, the named return value ret is initializedwith zero. The nameless function in the defer increments the value of retwith 1. The return 0 on line5 will not be the returned value, because of defer. The function f willreturn 1!