This is a creation in Article, where the information may have evolved or changed.
The Go language delay function defer acts as a cry...catch and is very easy to use, but in practical applications, many gopher do not really understand the order of execution between defer, return, and return values, thus falling into the pit, Today we will unveil the mystery of it!
First, run the following two segments of code:
A. Cases of nameless return values
Package Mainimport ("FMT") func main () {FMT. Println ("Return:", A ())//Prints the result to return:0}func a () int {var i intdefer func () {i++fmt. Println ("Defer2:", i)//print result is defer:2} () defer func () {i++fmt. Println ("Defer1:", i)//print result is defer:1} () return i}
B. Case of a well-known return value
Package Mainimport ("FMT") func main () {FMT. Println ("Return:", B ())//Prints the result to Return:2}func B () (i int) {defer func () {i++fmt. Println ("Defer2:", i)//print result is defer:2} () defer func () {i++fmt. Println ("Defer1:", i)//print result is defer:1} () return I//or direct return effect is the same}
Let's start by assuming a conclusion to help you understand why:
The order of execution of multiple defer is "LIFO";
Defer, return, return value three of the execution logic should be: return first execution, return is responsible for writing the results to the return value, and then defer began to perform some finishing work; Finally the function carries the current return value exit.
How to explain the difference between the two results:
The result of the above two pieces of code is different, in fact, from the 2nd conclusion is very good understanding.
The return value of the A () int function is not pre-named, its value is derived from the assignment of other variables, and the other variable is modified in defer, not the return value itself, so the return value is not changed when the function exits.
The return value of the B () (I int) function is well known in advance, which means that the defer can be called to the real return value, so defer modifies the value of I once again after the return assignment returns the value I, and the return value after the function exits is the defer modified value.
C. Let's look at a third example to verify the above conclusion:
Package Mainimport ("FMT") func main () {FMT. Println ("C return:", * (C ()))//Prints the result as C RETURN:2}FUNC C () *int {var i intdefer func () {i++fmt. Println ("C Defer2:", i)//print result is C defer:2} () defer func () {i++fmt. Println ("C defer1:", i)//print result is C defer:1} () return &i}
Although the return value of the C () *int is not declared in advance, since the return value of the C () *int is a pointer variable, after return assigns the address of the variable I to the return value, defer modifies the actual value of I in memory again, So the return value of the function exit is still the original pointer address, but the actual value of the memory it points to has been successfully modified.
That is, we assume that the conclusion is correct!