01 Introduction
What is defer
defer is a mechanism provided by the Go language for registering delayed calls to ensure that some resources are recycled and released.
Defer registered delayed call can be executed after the current function is executed (including the normal ending through return or the exception ending caused by panic)
When the function or expression registered by defe is executed in reverse order, the one registered first and then executed, similar to the stack "first in, then out"
Let's see an example below:
package main import "fmt" func main() { f() } func f() { defer func() { (1) }() defer func() { (2) }() defer func() { (3) }() }
Output:
3
2
1
How to use defer
Free up resources
Using defer can avoid resource leakage to a certain extent, especially in scenarios where there are many return statements. It is easy to forget or the resource is not closed due to logical errors.
The following program is because the statement that closes the resource is not executed after using return, resulting in resource leakage:
f, err := ("") if err != nil { return } () ()
Better here are as follows:
f, err := ("") if err != nil { return } defer () // Operate the filef,process()
Here, when the program executes smoothly, defer will release resources; defer needs to be registered first and then used. For example, when the file is opened, the current function will be exited when the program executes the return statement without defer, so defer will not be executed here
defer catches exception
There is no try and catch in go, and when the program has an exception, we need to recover from the exception. At this time, we can use defer + recover for exception capture
func f() { defer func() { if err := recover(); err != nil { (err) } }() // do something panic("panic") }
Note that the recover() function is only valid when called with anonymous function in defer, and the following programs cannot perform exception capture:
func f() { if err := recover(); err != nil { (err) } // do something panic("panic") }
Implement code tracking
The following provides a method to trace information about entering or leaving a function when a program is reached. This can be used to test whether a specific function has been executed.
func trace(msg string) { ("entering:", msg) } func untrace(msg string) { ("leaving:", msg) }
Record the parameters and return values of the function
Sometimes the program returns the result that does not meet expectations. You may manually print log debugging. At this time, use defer to record the parameters and return values of the function to avoid manually printing debugging statements.
func func1(s string) (n int, err error) { defer func() { ("func1(%q) = %d, %v", s, n, err) }() return 7, nil }
Implement code tracking and record the parameters and return values of the function
In Go language, defer is generally used to release resources, or to use defer to call an anonymous function, and use recover() to handle exception panic in anonymous functions.
When using defer, it is also easy to encounter traps. In this article, we will introduce the traps when using defer.
02 defer trap
The defer statement cannot be followed by the return statement.
Sample code:
func main() { name := GetUserName("phper") ("name:%s\n", name) if name != "gopher" { return } defer ("this is a defer call") } func GetUserName(name string) string { return name }
Output result:
name:phper
Read the above code, we execute the defer statement after the return statement. By outputting the result, we can find that the defer statement call is not executed.
Although defer can be anywhere in the function body, we also need to pay special attention to whether the position where defer can be executed.
The defer statement executes anonymous functions and preprocesses parameters.
Sample code:
func main() { var count int64 defer func(data int64) { ("defer:", data) }(count + 1) count = 100 ("main:", count) }
Output result:
main: 100
defer: 1
Reading the above code, first we define a variable count of type int64, and then use the defer statement to execute an anonymous function. The anonymous function passes the parameter count + 1, and finally the main function outputs 100, and the anonymous function executed by defer outputs 1.
Because when executing the defer statement, count + 1 is executed, and it is stored first, and wait until the main function where defer is located is executed, and then execute the code in the function body of the anonymous function called by the defer statement.
03 Summary
This article mainly introduces the pitfalls you may encounter when using defer statements. The defer statement cannot be after the return statement; the anonymous functions executed by the defer statement, and the parameters of the anonymous function will be pre-processed.
This is the end of this article about the traps of defer use in Go. For more relevant content on defer use in Go, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!