<\/span><\/h1>\n\n\n\nDefer as the name suggests is used to defer the cleanup activities in a function. These cleanup activities will be performed at the end of the function. This cleanup activities will be done in a different function called by defer. This different function is called at the end of the surrounding function before it returns. Below is the syntax of defer function<\/p>\n\n\n\n
defer {function_or_method_call}<\/code><\/pre>\n\n\n\nThings to note about defer function<\/p>\n\n\n\n
- Execution of a deferred function is delayed to the moment the surrounding function returns<\/li>
- deferred function will also be executed if the enclosing function terminates abruptly. For example in case of a panic<\/li><\/ul>\n\n\n\n
One good example of understanding the defer<\/strong> function is to look at the use case of writing to a file. A file that is opened for writing also must be closed. <\/p>\n\n\n\npackage main\n\nimport (\n \"fmt\"\n \"log\"\n \"os\"\n)\n\nfunc main() {\n err := writeToTempFile(\"Some text\")\n if err != nil {\n log.Fatalf(err.Error())\n }\n fmt.Printf(\"Write to file succesful\")\n}\n\nfunc writeToTempFile(text string) error {\n file, err := os.Open(\"temp.txt\")\n if err != nil {\n return err\n }\n n, err := file.WriteString(\"Some text\")\n if err != nil {\n return err\n }\n fmt.Printf(\"Number of bytes written: %d\", n)\n file.Close()\n return nil\n}<\/code><\/pre>\n\n\n\nIn the above program, in the writeToTempFile <\/strong>function, we are opening a file and then trying to write some content to the file. After we have written the contents of the file we close the file. It is possible that during the write operation it might result into an error and function will return without closing the file. Defer<\/strong> function helps to avoid these kinds of problems. Defer<\/strong> function is always executed before the surrounding function returns. Let’s rewrite the above program with a defer<\/strong> function here.<\/p>\n\n\n\npackage main\n\nimport (\n \"fmt\"\n \"log\"\n \"os\"\n)\n\nfunc main() {\n err := writeToTempFile(\"Some text\")\n if err != nil {\n log.Fatalf(err.Error())\n }\n fmt.Printf(\"Write to file succesful\")\n}\n\nfunc writeToTempFile(text string) error {\n file, err := os.Open(\"temp.txt\")\n if err != nil {\n return err\n }\n defer file.Close()\n\n n, err := file.WriteString(\"Some text\")\n if err != nil {\n return err\n }\n fmt.Printf(\"Number of bytes written: %d\", n)\n return nil\n}<\/code><\/pre>\n\n\n\nIn the above program, we do defer file.Close()<\/strong> after opening the file. This will make sure that closing of the file is executed even if the write to the file results into an error. Defer function makes sure that the file will be closed regardless of number of return statements in the function<\/p>\n\n\n\n<\/span>Custom Function in defer<\/strong><\/span><\/h1>\n\n\n\nWe can also call a custom function in defer<\/strong>. Let’s see an example for that<\/p>\n\n\n\npackage main\nimport \"fmt\"\nfunc main() {\n defer test()\n fmt.Println(\"Executed in main\")\n}\nfunc test() {\n fmt.Println(\"In Defer\")\n}<\/code><\/pre>\n\n\n\nOutput<\/strong><\/p>\n\n\n\nExecuted in main\nIn Defer<\/code><\/pre>\n\n\n\nIn the above program there is a defer<\/strong> statement calling the custom function named test<\/strong>. As seen from the output, the test<\/strong> function is called after everything in the main is executed and before main returns. That is why<\/p>\n\n\n\nExecuted in main<\/code><\/pre>\n\n\n\nis printed before<\/p>\n\n\n\n
In Defer<\/code><\/pre>\n\n\n\nThe above function also shows that it is perfectly ok to use defer in the main function as well.<\/p>\n\n\n\n
<\/span>Inline Function in Defer<\/strong><\/span><\/h1>\n\n\n\nIt is also possible to have an inline function with defer. Let’s see an example of that.<\/p>\n\n\n\n
package main\n\nimport \"fmt\"\n\nfunc main() {\n defer func() { fmt.Println(\"In inline defer\") }()\n fmt.Println(\"Executed\")\n}<\/code><\/pre>\n\n\n\nOutput<\/strong><\/p>\n\n\n\nExecuted\nIn inline defer<\/code><\/pre>\n\n\n\nIn the above code we have defer<\/strong> with a inline function<\/p>\n\n\n\ndefer func() { fmt.Println(\"In inline defer\") }()<\/code><\/pre>\n\n\n\nThis is allowed in go. Also note that it is mandatory to add “()”<\/strong> after the function otherwise compiler will raise error<\/p>\n\n\n\nexpression in defer must be function call<\/code><\/pre>\n\n\n\nAs seen from the output, that the inline function is called after everything in the main is executed and before main returns. That is why<\/p>\n\n\n\n
Executed in main<\/code><\/pre>\n\n\n\nis printed before<\/p>\n\n\n\n
In inline Defer<\/code><\/pre>\n\n\n\n<\/span>How does defer works<\/strong><\/span><\/h1>\n\n\n\nWhen the the compiler encounter a defer statement in a function it pushes it onto a list. This list internally implements a stack data structure. All the encountered defer statement in the same function are pushed onto this list. When the surrounding function returns then all the functions in the stack starting from top to bottom are executed before execution can begin in the calling function. Now same thing will happen in the calling function as well.<\/p>\n\n\n\n
Let’s understand what happens when we have multiple defer functions in different functions. Imagine a function call from main<\/strong> function to f1<\/strong> function to f2<\/strong> function<\/p>\n\n\n\nmain<\/strong>->f1<\/strong>->f2<\/strong><\/p>\n\n\n\nBelow is the sequence that will be happening after f2 returns<\/p>\n\n\n\n
- Defer functions in f2<\/strong> will be executed if present. Control will return to the caller which is a function f1<\/strong>.<\/li><\/ul>\n\n\n\n
- Defer functions in f1<\/strong> will be executed if present. Control will return to the caller which is a function main<\/strong>. Note that if there are more functions in between then the process will continue up the stack in a similar way<\/li><\/ul>\n\n\n\n
- After main returns the defer function if present in main will be executed<\/li><\/ul>\n\n\n\n
Let’s see a program for that<\/p>\n\n\n\n
package main\n\nimport \"fmt\"\n\nfunc main() {\n\tdefer fmt.Println(\"Defer in main\")\n\tfmt.Println(\"Stat main\")\n\tf1()\n\tfmt.Println(\"Finish main\")\n}\n\nfunc f1() {\n\tdefer fmt.Println(\"Defer in f1\")\n\tfmt.Println(\"Start f1\")\n\tf2()\n\tfmt.Println(\"Finish f1\")\n}\n\nfunc f2() {\n\tdefer fmt.Println(\"Defer in f2\")\n\tfmt.Println(\"Start f2\")\n\tfmt.Println(\"Finish f2\")\n}<\/code><\/pre>\n\n\n\nOutput<\/strong><\/p>\n\n\n\nStat main\nStart f1\nStart f2\nFinish f2\nDefer in f2\nFinish f1\nDefer in f1\nFinish main\nDefer in main<\/code><\/pre>\n\n\n\n<\/span>Evaluation of defer arguments<\/strong><\/span><\/h1>\n\n\n\ndefer arguments are evaluated at the time defer statement is evaluated<\/p>\n\n\n\n
Let’s see a program for that<\/p>\n\n\n\n
package main\n\nimport \"fmt\"\n\nfunc main() {\n\tsample := \"abc\"\n\n\tdefer fmt.Printf(\"In defer sample is: %s\\n\", sample)\n\tsample = \"xyz\"\n}<\/code><\/pre>\n\n\n\nOutput<\/strong><\/p>\n\n\n\nIn defer sample is: abc<\/code><\/pre>\n\n\n\nIn the above program when the defer statement was evaluated the value of the sample<\/strong> variable was “abc”<\/strong>. In the defer function, we print the sample variable. After the defer statement we change the value of the sample<\/strong> variable to “xyz”<\/strong>. But the program outputs “abc”<\/strong> instead of “xyz”<\/strong> because when the defer arguments were evaluated the value of the sample variable was “abc”<\/strong>.<\/p>\n\n\n\n