This is a creation in Article, where the information may have evolved or changed.
About delay call functions (Deferred function Calls)
The syntax for the delay call function is as follows:
defer func_name(param-list)
When a function call has a keyword defer , the execution of the function is deferred until the function containing the defer statement is about to return. For example:
func main() { defer fmt.Println("Fourth") fmt.Println("First") fmt.Println("Third")}
The final print order is as follows:
FirstSecondThird
需要注意的是, defer 调用的函数参数的值 defer 被定义时就确定了.
For example:
i := 1defer fmt.Println("Deferred print:", i)i++fmt.Println("Normal print:", i)
The printed content is as follows:
Normal print: 2Deferred print: 1
So we know that in the "defer FMT." Println ("Deferred print:", i) "When called, the value of I has been determined, thus equivalent to defer FMT. Println ("Deferred Print:", 1) .
需要强调的时, defer 调用的函数参数的值在 defer 定义时就确定了, 而 defer 函数内部所使用的变量的值需要在这个函数运行时才确定.
For example:
func f1() (r int) { r = 1 defer func() { r++ fmt.Println(r) }() r = 2 return}func main() { f1()}
In the above example, the final print is "3", because after the "R = 2" assignment, the defer function is executed, so within this function, the value of R is 2 and the increment becomes 3.
Defer order
If there are multiple defer calls, the order of the calls is in the advanced order, similar to the stack-out:
func main() { defer fmt.Println(1) defer fmt.Println(2) defer fmt.Println(3) defer fmt.Println(4)}
The first thing to do is "FMT." PRINTLN (4) ", followed by" FMT. PRINTLN (3) "And so on, the final output is as follows:
4321
Defer attention points
defer 函数调用的执行时机是外层函数设置返回值之后, 并且在即将返回之前
.
For example:
func f1() (r int) { defer func() { r++ }() return 0}func main() { fmt.Println(f1())}
Above FMT. What does Println (F1 ()) print? Many friends may think that the print is 0, but the correct answer is 1. What is this for?
To figure this out, we need to keep two points in mind.
defer 函数调用的执行时机是外层函数设置返回值之后, 并且在即将返回之前
return XXX 操作并不是原子的.
Let's rewrite the example above and everyone will understand:
func f1() (r int) { defer func() { r++ }() r = 0 return}
The defer function is called after the assignment operation "R = 0", and finally the return statement.
So the above code is equivalent to:
func f1() (r int) { r = 0 func() { r++ }() return}
Now let's look at a more interesting example:
func double(x int) int { return x + x}func triple(x int) (r int) { defer func() { r += x }() return double(x)}func main() { fmt.Println(triple(3))}
If we have understood what is said above, then the triple function is well understood, and it is actually:
func triple(x int) (r int) { r = double(x) func() { r += x }() return}
Usage Scenarios for defer expressions
Defer are commonly used in Open/close, Connect/disconnect, Lock/unlock, and other paired operations to ensure that resources are released correctly under any circumstances. In this perspective, the defer operation and the try ... finally statement block in Java have similarities.
For example:
var mutex sync.Mutexvar count = 0func increment() { mutex.Lock() defer mutex.Unlock() count++}
In the increment function, we use a Mutex to lock up to avoid the appearance of race conditions. In concurrent programming, locking is forgotten (or, in some cases, unlock is not executed), which often results in disastrous consequences. In any case, it is necessary to ensure that after the lock operation, the corresponding unlock operation, we can use the defer call unlock operation.