In Go,defer
A statement is used to delay the execution of a function call until the function containing it returns. whendefer
Statements nested infor
When in a loop, its execution timing still followsdefer
The basic rules of , but pay attention to the context returned by the loop and function.
Basic Rules
-
Delayed execution:
defer
A statement will be executed when the function containing it returns, regardless of whether the function returns normally or due to errors, panics, etc. -
Last In First Out (LIFO): If there are multiple
defer
statements, they will be executed in the order of back in first out.
Use defer in for loop
whendefer
Statements nested infor
When in a loop, its execution timing is related to the context of the loop:
1. The defer in the body
ifdefer
The statement is located infor
Inside the loop body, it is recorded at the end of each loop iteration, but the actual execution time depends on when the function where the loop is located returns.
2. Execute when the function returns
No matter how many times the loop is executed,defer
Statements are executed in the order of records when the function containing it returns.
Sample code
Here is a sample code to help understanddefer
existfor
Behavior in a loop:
package main import "fmt" func main() { for i := 0; i < 3; i++ { defer ("Deferred in loop iteration:", i) } ("Loop finished") }
Output result:
Loop finished
Deferred in loop iteration: 2
Deferred in loop iteration: 1
Deferred in loop iteration: 0
explain:
- Circulate in the body
defer
The statement is recorded at the end of each iteration. - After the loop is over, the program continues to execute until
main
The function returns. - exist
main
When the function returns,defer
The statement is executed in the order of the last iteration first, that is, the last iteration is executed first.defer
, execute the previous one again, and so on.
Things to note
-
Performance issues: Use frequently in loops
defer
This may cause performance issues, as a delayed call is logged in each iteration. -
Variable Capture:if
defer
The statement captures loop variables (e.g.i
), which may lead to unexpected behavior. For example, ifdefer
What is captured is a reference to a variable, not a value, which may result in alldefer
The statement prints the same value.
If infor
Nested in a loopdefer
A call is a function, rather than directly printing the value, the output result may vary depending on the implementation of the function. In particular, if the variable is captured inside the function (such as loop variablesi
), which may lead to some unexpected behavior.
Example 1: defer call a function to capture the value of a loop variable
If the function captures the value of the loop variable (passed through parameters), then each calldefer
The value of the current iteration will be recorded. In this case, the output result is similar to the direct printing value.
package main import "fmt" func printDeferred(value int) { ("Deferred value:", value) } func main() { for i := 0; i < 3; i++ { defer printDeferred(i) } ("Loop finished") }
Output result:
Loop finished
Deferred value: 2
Deferred value: 1
Deferred value: 0
explain:
- Each iteration,
defer
CalledprintDeferred
function and the current onei
Passed as a parameter to the function. - The function captures the value of the variable, so the value of the current iteration is recorded in each iteration.
- When the function returns,
defer
Execute in the order of first out.
Example 2: defer call a function to capture references to loop variables
If the function captures a reference to a loop variable (such as using variables directlyi
, instead of passing values through parameters), then alldefer
The output of the call may be the same because they all refer to the same variable.
package main import "fmt" func printDeferred() { ("Deferred value:", i) } func main() { for i := 0; i < 3; i++ { defer printDeferred() } ("Loop finished") }
Output result:
Loop finished
Deferred value: 3
Deferred value: 3
Deferred value: 3
explain:
- exist
for
In the loop,defer
CalledprintDeferred
function, but no parameters are passed. - The variable is accessed directly within the function.
i
, so what is captured is a reference to the variable. - when
defer
When executing, the loop has ended.i
The value of is 3 (the value after the end of the loop). - all
defer
The calls are all printed 3 because they refer to the same variable.
Example 3: defer calls a function to capture the value of a loop variable (closure)
If the function is a closure that captures the value of the loop variable, then each iteration captures the value of the current iteration.
package main import "fmt" func main() { for i := 0; i < 3; i++ { defer func(value int) { ("Deferred value:", value) }(i) } ("Loop finished") }
Output result:
Loop finished
Deferred value: 2
Deferred value: 1
Deferred value: 0
explain:
- Each iteration,
defer
An anonymous function was called and the current one wasi
Passed as a parameter to the closure. - The closure captures the value of the variable, so the value of the current iteration is recorded in each iteration.
- When the function returns,
defer
Execute in the order of first out.
Summarize
ifdefer
The call is a function, and the output result will be affected by the following factors:
-
Whether a function captures the value or reference of a variable:
- If the value is captured (passed by parameters), the value of the current iteration is recorded for each iteration.
- If what is captured is a reference (direct access to the variable), then all
defer
The call may print the same value (value after the end of the loop).
- Use of closures: If you use a closure to capture the value of a variable, the value of the current iteration will be recorded in each iteration.
Therefore, usedefer
When paying attention to the details of variable capture, you need to avoid unexpected behavior.
Summarize
existfor
Nested in a loopdefer
hour,defer
The statement is recorded at the end of each iteration, but the actual execution time is when the function containing it returns. understanddefer
The execution rules and context are very important to avoid unexpected behavior.
This is the article about the execution order of nested defers in the go language for loop. For more information about the execution order of go language defers, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!