Defer
Defer is a way of handling the resources that go provides. The use of defer follows 3 principles when the defer expression is calculated, the parameters of the defer function are also calculated. The following defer expression println operation, its entry I will also be evaluated, the result is the initialization value of 0, so the defer call will print "0"
func a() {i := 0defer fmt.Println(i)i++return
The defer function follows a last-in-first-out invocation principle after a function return, with the following printing result of 3210
func b() { for i := 0; i < 4; i++ { defer fmt.Print(i) }}
The defer function may read and assign values to the return value of the function in which the return value is 2.
Func C () (i int) {
Defer func () {i++} ()
Return 1
}
There are three scenarios for the above 3rd:
例1:<br>func f() (result int) { defer func() { result++ }() return 0} 例2:<br>func f() (r int) { t := 5 defer func() { t = t + 5 }() return t} 例3:<br>func f() (r int) { defer func(r int) { r = r + 5 }(r) return 1}
The procedure for returning a function is to assign a value to the return value before calling the defer expression, and finally to return to the calling function.
First Look at example 1, which can be rewritten like this:
func f() (result int) { result = 0 //return语句不是一条原子调用,return xxx其实是赋值+ret指令 func() { //defer被插入到return之前执行,也就是赋返回值和ret指令之间 result++ }() return}
So this return value is 1.
Look again at Example 2, which can be rewritten like this:
func f() (r int) { t := 5 r = t //赋值指令 func() { //defer被插入到赋值与返回之间执行,这个例子中返回值r没被修改过 t = t + 5 } return //空的return指令}
So the result of this is 5.
Finally look at example 3, which is rewritten to become:
func f() (r int) { r = 1 //给返回值赋值 func(r int) { //这里改的r是传值传进去的r,不会改变要返回的那个r值 r = r + 5 }(r) return //空的return}
So the result of this example is 1.
Panic and recover
The following principles apply to the use of panic and recover:
defer 需要放在 panic 之前定义,另外recover只有在 defer 调用的函数中才有效。recover处理异常后,逻辑并不会恢复到 panic 那个点去,函数跑到 defer 之后的那个点.多个 defer 会形成 defer 栈,后定义的 defer 语句会被最先调用
The use of errors in the Recover capture program is as follows
package main import ( "fmt" "time") func main() { f() fmt.Println("end")} func f() { defer func() { //必须要先声明defer,否则不能捕获到panic异常 fmt.Println("defer start") if err := recover(); err != nil { fmt.Println(err) //这里的err其实就是panic传入的内容,"bug" } fmt.Println("defer end") }() for { fmt.Println("func begin") a := []string{"a", "b"} fmt.Println(a[3]) // 越界访问,肯定出现异常 panic("bug") // 上面已经出现异常了,所以肯定走不到这里了。 fmt.Println("func end") // 不会运行的. time.Sleep(1 * time.Second) }}
The output is as follows
1 func begin
2 Defer start
3 runtime Error:index out of range
4 Defer end
5 End