SoFunction
Updated on 2024-11-10

An article explaining the execution order of go's defer and return.

Explaining the execution order of go's defer and return in detail

go's defer and return are two keywords in golang, return is used to return the return value of the function, you can also participate in certain process control, such as the following code, return short-circuits the output of the latter

package main

import "fmt"

// The details of defer and return
func main() {
	foo(2)
	foo(1)
}
func foo(i int) {
	(i)
	if i == 1 {
		return
	}
	(i + 1)
}

Results:

2
3
1

The first output outputs i and i+1 in full, the second output is short-circuited and only outputs 1

defer is a delayed call in golang, often used for file stream closure, lock unlocking operations, the operation after the defer will be called after the end of the current function or goroutine

package main

import "fmt"

// The details of defer and return
func main() {
	foo()
}
func foo() {
	defer ("println defer")
	("println foo")
}

exports:
println foo
println defer

Defer itself has some characteristics, such as the order of execution between defer and defer is first in, first out, first defer the last execution, analyze the following code:

package main

import "fmt"

// The details of defer and return
func main() {
	foo()
}
func foo() {
	defer ("floor 3")
	defer ("floor 2")
	("floor 1")
}

exports:
floor 1
floor 2
floor 3

According to this feature, if there is a possibility of panic in the code of our defer call, in order to keep the system running, we should recover before rather than after the

ackage main

import "fmt"

// The details of defer and return
func main() {
	foo()
}
func foo() {
	defer func() {
		panic("panic test")
	}()
	defer func() {
		if err := recover(); err != nil {
			("catch panic:", err)
		}
	}()
}

exports:
panic: panic test
package main

import "fmt"

// The details of defer and return
func main() {
	foo()
}
func foo() {
	defer func() {
		if err := recover(); err != nil {
			("catch panic:", err)
		}
	}()
	defer func() {
		panic("panic test")
	}()
}
exports:
catch panic: panic test

Interaction of defer and return

The interplay between defer and return is mainly expressed in the return value, consider the following code and what the output should be:

import "fmt"

// The details of defer and return
func main() {
	(foo1())
	(foo2())
	(foo3())
}
func foo1() int {
	i := 1
	defer func() { i++ }()
	return i
}
func foo2() (i int) {
	i = 1
	defer func() { i++ }()
	return i
}
func foo3() (i int) {
	defer func() { i++ }()
	return 1
}

Output:

1
2
2

The reasons for the above are

existfoo1 function.defer The closure in the statement will be executed after the function returns, but at that point the return value has been determined to be the1 so it ends up returning1 。

existfoo2 function that uses the named return valuei 。defer The closure in the statement modifies this named return value, so it returns the2 。

existfoo3 function, which also uses the named return valuei ,defer The closure in the statement modifies this named return value, and the function returns directly to the1 Libyan Arab Jamahiriyadefer The changes in2 。

And another feature of return that affects the order in which the code in return and defer is executed

package main

import "fmt"

// The details of defer and return
func main() {
	(foo1())

}
func foo1() int {
	defer func() { ("This is defer") }()
	return func() int {
		("This is return")
		return 1
	}()
}

exports:
This is return
This is defer
1

The reason for the above output is that return is non-atomic, defer will be executed before the return return value, but the statements in the return, will be executed in their entirety until the return anchors a value or names the return value, then the defer statement will be executed, and finally this value anchored by the return will be returned

to this article on a detailed explanation of go defer and return order of execution of the article is introduced to this, more related to go defer and return order of execution of the content please search for my previous articles or continue to browse the following related articles I hope you will support me in the future more!