Defer is a Golang construct that is usually used for code clean-up operations like ensuring you’ve closed a file or unlocked a lock. When defer is called, the call is performed at the end of that particular function call. Multiple defer calls are added to a list that is executed in Last In, First Out (LIFO) order.
In other languages, this functionality is similar to the ensure or finally keywords.
In the following examples, we will explore a practical file handling example and then take a closer look at the LIFO ordering of multiple defer calls.
In this example, we will create a file, defer closing it, and call a write call. Notice how the write call happens before the defer call despite the apparent ordering in the code. This is because defer is called at the end of the function (main) call.
package mainimport ("fmt""os")// code driver with 3 function callsfunc main() {f := createFile("/tmp/defer.txt")// we defer the close file call so we do not forget to handle// function executes after the last line of code of maindefer closeFile(f)writeFile(f)}// function creates a file with error checkingfunc createFile(p string) *os.File {fmt.Println("creating")f, err := os.Create(p)if err != nil {panic(err)}return f}// function writes to a filefunc writeFile(f *os.File) {fmt.Println("writing")fmt.Fprintln(f, "data")}// function closes a file with error checkingfunc closeFile(f *os.File) {fmt.Println("closing")err := f.Close()if err != nil {fmt.Fprintf(os.Stderr, "error: %v\n", err)os.Exit(1)}}
package mainimport ("fmt")func main() {// notice the LIFO order of output// Feel free to remove the defer statement and runningfor i := 1; i < 5; i++ {defer fmt.Println(i)}}
Free Resources