This is a creation in Article, where the information may have evolved or changed.
Objective
We all know that the defer function of the go language is very powerful, it is very convenient for resource management, but if it doesn't work well, there will be a trap, too. The Go language delay function defer acts as the Try...catch, the use is also very simple, then the defer, return, return value, panic between the execution order is what kind of, below we 1.1 points to uncover its mysterious veil! Don't talk more, come and see the introduction.
Defer introduction
The defer statement is used to perform function calls before the function is returned. This definition may seem complex, but it is easy to understand through an example.
package mainimport ("fmt")func finished() {fmt.Println("finished")}func largest() {defer finished()fmt.Println("largest()执行")}func main() {largest()}
That is, the action performed before the Func End (return). Whether defined before or after a normal statement.
Defer also supports invocation of methods.
package mainimport ("fmt")type person struct {firstName stringlastName string}func (p person) fullName() {fmt.Printf("%s %s",p.firstName,p.lastName)}func main() {p := person {firstName: "John",lastName: "Smith",}defer p.fullName()fmt.Printf("Welcome ")}
Ps:defer declares the value of the determined parameter first, and defer defers only its function body
import ( "fmt")func printA(a int) { fmt.Println("value of a in deferred function", a)}func main() { a := 5 defer printA(a) a = 10 fmt.Println("value of a before deferred function call", a)}
When defer is declared, its parameter a value is parsed in real time and does not execute the contents of the function body, so subsequent modifications do not affect the current parameter values.
Validation results:
package mainimport ("fmt""time")func main() {defer P(time.Now())time.Sleep(5*time.Second)fmt.Println("main ", time.Now())}func P(t time.Time) {fmt.Println("defer", t)fmt.Println("P ", time.Now())}
Execution Result:
main 2018-03-16 14:43:25.10348 +0800 CST m=+5.003171200defer 2018-03-16 14:43:20.1033124 +0800 CST m=+0.003003600P 2018-03-16 14:43:25.142031 +0800 CST m=+5.041722200
Defer LIFO
A simple understanding is executed after the defer is declared (the defer statement is executed in reverse order).
package mainimport ( "fmt")func main() { name := "Naveen" fmt.Printf("Orignal String: %s\n", string(name)) for _, v := range []rune(name) { defer fmt.Printf("%c", v) }}
Output is: Neevan
Order of execution between Defer/return/return values/Panic
Now we analyze their order of execution in two different situations:
1. Return value assignment before returning
2. Check if there are defer and perform
3. Final return carry return value Exit function
First type: Anonymous return value
package mainimport ("fmt")func main() {fmt.Println("a return:", a()) // 打印结果为 a return: 0}func a() int {var i intdefer func() {i++fmt.Println("a defer2:", i) // 打印结果为 a defer2: 2}()defer func() {i++fmt.Println("a defer1:", i) // 打印结果为 a defer1: 1}()return i}
Output Result:
a defer1: 1a defer2: 2a return: 0
Explanation: The anonymous return value is declared before return (for type reason, type 0 value is 0), defer cannot access anonymous return value, so the return value is 0, and defer is the variable I defined before the operation.
Imagine: If the return value here is a pointer type, then will the output change?
Second type: Named return value
package mainimport ("fmt")func main() {fmt.Println("a return:", a()) // 打印结果为 b return: 2}func a() (i int) {defer func() {i++fmt.Println("a defer2:", i) // 打印结果为 b defer2: 2}()defer func() {i++fmt.Println("a defer1:", i) // 打印结果为 b defer1: 1}()return i // 或者直接 return 效果相同}
Output Result:
a defer1: 1a defer2: 2a return: 2
Explanation: The named return value is declared at the same time as the function declaration. Therefore, defer can access the named return value. The value returned after return is actually a defer modified value.
Defer scope
Defer in what circumstances will not be executed? A few examples are listed below:
1. When any one (master) panic occurs, it executes the defer declared before panic in the current process;
func main() {fmt.Println("...")panic(e) // defer 不会执行defer fmt.Println("defer")}
2. The os.Exit(int) defer will no longer be executed when the active call exits the process.
func main() {fmt.Println("...")os.Exit(1) // defer 不会执行defer fmt.Println("defer")}
func main() {fmt.Println("...")defer fmt.Println("defer")os.Exit(1) // defer 不会执行}
3. In the Panic (master) process, if there is not a defer call recover() to recover, it will cause the whole process to crash after the defer declared before execution is completed;
func main() {fmt.Println("...")defer fmt.Println("defer1")defer fmt.Println("defer2")defer fmt.Println("defer3")panic("error") // defer 会执行}
4. Defer only valid for current (master) Association
package mainimport ("fmt")func main() {fmt.Println("...")go func() { panic("err") }() // defer 执行defer fmt.Println("defer1")defer fmt.Println("defer2")defer fmt.Println("defer3")}
Practical use of defer
No matter what business or program, the delay is used where the function call is executed.
Example:
Post-Update