前言
大家都晓得Go编程中,假如在函数F里,执行了defer A(),那在函数F失常return之前或者因为panic要完结运行之前,被defer关键字润饰的函数调用A()都会被执行到。
比方上面的2个例子:
test1()会在main完结之前执行
// defer1.gopackage mainimport ( "fmt")func test1() { fmt.Println("test")}func main() { fmt.Println("main start") defer test1() fmt.Println("main end")}
这个例子输入的后果是:
main startmain endtest
test1()会在panic之前执行
// defer2.gopackage mainimport ( "fmt")func test1() { fmt.Println("test")}func test2() { panic(1)}func main() { fmt.Println("main start") defer test1() test2() fmt.Println("main end")}
这个例子输入的后果是:
main starttestpanic: 1goroutine 1 [running]:main.test2(...) /path/to/defer2.go:13main.main() /path/to/defer2.go:18 +0xb8exit status 2
问题
如果在函数F里,defer A()这个语句执行了,是否意味着A()这个函数调用肯定会执行?
这里大家能够先脑补一会。
请看上面的例子:
// defer3.gopackage mainimport ( "fmt" "os")func test1() { fmt.Println("test")}func main() { fmt.Println("main start") defer test1() fmt.Println("main end") os.Exit(0)}
下面的代码运行后果会是怎么样?
论断
下面defer3.go执行的后果是:
main startmain end
被defer的test1()并没有在main完结之前执行。这是为什么呢?
查看os.Exit的阐明如下:
Exit causes the current program to exit with the given status code. Conventionally, code zero indicates success, non-zero an error. The program terminates immediately; deferred functions are not run.For portability, the status code should be in the range [0, 125].
如果在函数里是因为执行了os.Exit而退出,而不是失常return退出或者panic退出,那程序会立刻进行,被defer的函数调用不会执行。
defer 4准则回顾
defer前面跟的必须是函数或者办法调用,defer前面的表达式不能加括号。
defer (fmt.Println(1)) // 编译报错,因为defer前面跟的表达式不能加括号
被defer的函数的参数在执行到defer语句的时候就被确定下来了。
func a() { i := 0 defer fmt.Println(i) // 最终打印0 i++ return}
上例中,被defer的函数fmt.Println的参数i在执行到defer这一行的时候,i的值是0,fmt.Println的参数就被确定下来是0了,因而最终打印的后果是0,而不是1。
被defer的函数执行程序满足LIFO准则,后defer的先执行。
func b() { for i := 0; i < 4; i++ { defer fmt.Print(i) }}
上例中,输入的后果是3210,后defer的先执行。
被defer的函数能够对defer语句所在的函数的命名返回值做读取和批改操作。
// f returns 42func f() (result int) { defer func() { // result is accessed after it was set to 6 by the return statement result *= 7 }() return 6}
上例中,被defer的函数func对defer语句所在的函数f的命名返回值result做了批改操作。
调用函数f,返回的后果是42。
执行程序是函数f先把要返回的值6赋值给result,而后执行被defer的函数func,result被批改为42,而后函数f返回result,也就是返回了42。
官网阐明如下:
Each time a "defer" statement executes, the function value and parameters tothe call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred. Thatis, if the surrounding function returns through an explicit return statement, deferred functions are executed after any result parameters are set by that return statement but before the function returns to its caller. If a deferredfunction value evaluates to nil, execution panics when the function is invoked, not when the "defer" statement is executed.
代码
相干代码和阐明开源在GitHub:https://github.com/jincheng9/...
也能够搜寻公众号:coding进阶,查看更多Go常识。
一起提高!