SoFunction
Updated on 2025-03-03

Detailed explanation of the order of execution of Go defer and return

Learn what defer is first

The order of defer and return execution in Go language

The defer statement in Go language will delay the statement followed by it. When the defer belonging function is about to return, the delayed statement is executed in the reverse order of defer. That is to say, the defer statement is finally executed, and the defer statement is finally executed. (It is the same as the first entry and then exit of the stack, and it can also be understood as entering and exiting the stack)

Give a simple example

func main() {
   a, b := 111, 333
   defer ("b= ", b)
   ("a= ", a)
}
Print results:
a=  111
b=  333

You can see that although b is in front of the statement when executing the statement, the output result is b is output at the end.

How to use defer

(Simple explanation, please check the information yourself)

It is generally used to release resources or read and write operations. When processing paired operations in business or logic, it is a relatively tedious thing, such as opening and closing files, receiving requests and replying requests, locking and unlocking, etc. Among these operations, the easiest thing to ignore is to correctly release and close resources at each function exit. For example, the following example

func main(){
    a := 1
    out := ()
    defer ()
    (out, a)
}
Output result:
1

You can print the result to the console at the end, and similar uses such as closing the database resources, etc. If this example is too simple, then look at the next example.

var a bool = true
defer func() {
   ("1")
}()
if a == true {
   ("2")
   return
}
defer func() {
   ("3")
}()
Output result:
2
1

We will find that the defer statement also needs to be executed, if the return is executed before the defer function is executed. The statement after defer will not be executed again. However, if the defer has been executed before return, the statement in the defer will be executed first before return execution.

So what is the connection between defer and return?

defer is a delayed execution statement, and return is a return statement, so there must be a problem of who will come first and who will come later. Let's see a classic example below

func increaseA() int {
	var i int
	defer func() {
		i++
	}()
	return i
}
func increaseB() (r int) {
	defer func() {
		r++
	}()
	return r
}
func main() {
	(increaseA())
	(increaseB())
}
The output result is:
0
1

Some people must be confused, why does function A have no output, but function B have output? Why are the answers not 1 and 0?

reason:

Let’s talk about the conclusion first: Defer modified anonymous function can only update the named return value. So what problems will this cause? Let's analyze this example step by step.

  • There is a declaration in the increaseA() function, which means that i has been generated in the function and is a variable with a name. However, the function returns anonymous parameters.
  • r is not declared in the increaseB() function, it is an anonymous variable. However, the function returns the parameter as a named parameter.
  • func increasesA() int, when the return value i=0, the value has been bound to the return value, and it is useless to defer and change i.
  • func increasesB() (r int), the return value r first sets the return variable to 0, and defer changes r to 1. It can still take effect at this time. Therefore, the answers are obviously 1 and 0.

Go further to understand

If we want to further understand, we can output assembly statements and then study them. Unfortunately, I am a rookie and I can’t understand assembly language! But we can start with return

We need to understand the operation mechanism of return return value:

returnIt is not an atomic operation, it is divided into two steps: assignment and return value.returnTwo steps were performed because the return value was not named, soreturnA return value is specified by default (assuming it is a), first assign i to a. Since subsequent operations are performed for i, they will not affect a. After that, because a will not be updated,return aWill not change.

var i int  
a := i  
return a

But if the return parameter a is a named parameter, just like the increaseB() function in the above example. a is equivalent to the named variable i, because all operations are based on the named variable i(a), and the return value is also i, so every defer operation, the return value i will be updated.

Summary of the flow

return will save the return value first. For the nameless return value, it is saved in a temporary object, and defer cannot see the temporary object; for the nameless return value, it is saved in a named variable.

The above is a detailed explanation of the order of execution of Go defer and return. For more information on the order of execution of Go defer return, please pay attention to my other related articles!