SoFunction
Updated on 2025-03-01

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

Example

Directly upload the code

func test() int {
   result = 123
   defer func() {
      result = 456
   }()
   return result
}
func main() {
   (test())
}

result

123

Modified code

func test() (result int) {
   result = 123
   defer func() {
      result = 456
   }()
   return result
}
func main() {
   (test())
}

result

456

Look at the following example

func test() (result int) {
   result = 123
   defer func() {
      ("aaa")
      result = 456
   }()
   return func() int {
      ("bbb")
      return result
   }()
}
func main() {
   (test())
}

result

bbb
aaa
456

Which one is defer or return is executed first

This question is mainly which one is defer or return first. It is easy to understand that if there are multiple defers in a function, it is saved in the form of a stack, and it is executed first from the top of the stack when executing, that is, the defer defined later will be executed first, and the defer is executed after return execution.

Because defer is executed after return execution, it is easy to understand that in the third example, bbb first and aaa then print it.

The second and third example test functions return 456, is also easy to understand, because defer can change the variable defined in the return value. Although return has returned, defer can still change it.

In the first example, defer changes not the variable defined in the return value, but the local variable. At this time, return has been executed, and defer changes the local variable is useless. Changing the value of a local variable in defer has no effect. The first example returns result is a value copy, that is, copy the value of result and return it. Therefore, defer changing the result will not affect the return value.

In the second and third examples, the result returned by return is not a value copy, because result is a variable defined in the return value, so the return returns directly is that variable, and there is no value copy at this time.

Take a look at the following example

func test() *int {
   result := 123
   defer func() {
      result = 456
   }()
   return &result
}
func main() {
   (*test())
}

result

456

At this time, defer changes the local variable result and takes effect again. Why is this? This is because return returns the address of the local variable, not just copying of the local variable. Therefore, modifying local traversal in defer will affect the return result.

Summarize

The above description may be a bit confusing, and you need to experiment yourself and understand it carefully before you can truly understand it. Let me summarize my understanding below:

There are 2 ways to return:

Value copy: Copy the value of the local variable to the return value. return directly returns the value of the local variable (not a reference to the local variable)

Non-value copy: that is, return does not copy the value when returning the value. There are two situations:

  • Returns the variable defined in the return value.
  • Returns a reference to a local variable.

In the case of non-value copying, the defer modification return value is effective.

The execution of return takes two steps: 1. First assign the result of return to the return value; 2. Then assign the return value as the result of the function to the caller.

The execution of defer is performed in the middle of two steps of return. Therefore, if return value copy occurs, defer will not change the return result; if return value copy does not occur, defer will change the return result.

This is the article about detailing the execution order of defer and return in Go. For more related Go defer return content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!