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:
func ReadWrite() bool {
file.Open("file")
// Do your thing
if failureX {
file.Close() 1
return false
}
if failureY {
file.Close() 1
return false
}
file.Close() 1
return true 2
}
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
.
func ReadWrite() bool {
file.Open("filename")
defer file.Close() 1
// Do your thing
if failureX {
return false 2
}
if failureY {
return false 2
}
return true 2
}
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
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
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:
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:
defer func(x int) {/* ... */}(5)
In this (unnamed) function you can access any named return parameter:
func f() (ret int)
defer func() { 1
ret++
}()
return 0
}
Here 1 we specify our function, the named return value ret
is initializedwith zero. The nameless function in the defer increments the value of ret
with 1. The return 0
on line5 will not be the returned value, because of defer
. The function f
willreturn 1!