本文操作环境:windows10系统、go 1.11.2、thinkpad t480电脑。
(学习视频分享:编程视频)
用法介绍:
defer是go语言中的延迟执行语句,用来添加函数结束时执行的代码,常用于释放某些已分配的资源、关闭数据库连接、断开socket连接、解锁一个加锁的资源。go语言机制担保一定会执行defer语句中的代码。
其它语言中也有类似的机制,比如java、c#语言里的finally语句,c++语言里的析构函数(destructor)可以起类似的作用,c++语言机制担保在对象被销毁前一定会执行析构函数中的代码。c++中的析构函数析构的是对象,go中的defer析构的是函数。
一、defer语句执行时机
defer语句在函数返回之前 或者 函数中 return语句(return语句可能调用另一个函数) 之后执行。示例代码:
package main import ( "fmt") func main() { fmt.println(deferreturn())} func deferreturn() (ret int) { defer func() { ret++ }() return 10}
上述代码打印出来的值是:11。 defer语句 匿名函数中的“ret++” 对返回值 10 加 1 变成了 11。再来看一个defer语句出现在return语句之后的代码:
func returndefer() (ret int) { return 0 defer func() { ret++ ret++ }() return 1}
上述returndefer函数的返回值是:0。原因是defer语句还没有添加上代码执行到"return 0"函数就返回了,因此defer语句就没有执行。
二、多个defer语句的执行顺序是逆序执行
当出现多条 defer 语句时以逆序执行(类似栈,即后进先出)。示例代码:
func defersample() { for i := 0; i < 5; i++ { defer fmt.printf("%d ", i) }}
上述代码将会输出:4 3 2 1 0
三、defer与panic
1、在panic语句后面的defer语句不被执行
示例代码:
func panicdefer() { panic("panic") defer fmt.println("defer after panic")}
上述代码的输出如下:
panic: panicgoroutine 1 [running]:main.panicdefer() e:/godemo/testdefer.go:17 +0x39main.main() e:/godemo/testdefer.go:13 +0x20process finished with exit code 2
可以看到 defer 语句没有执行。
2、在panic语句前的defer语句会被执行
示例代码:
func deferpanic() { defer fmt.println("defer before panic") panic("panic")}
上述代码的输出如下:
defer before panicpanic: panicgoroutine 1 [running]:main.deferpanic() e:/godemo/testdefer.go:19 +0x95main.main() e:/godemo/testdefer.go:14 +0x20process finished with exit code 2
defer 语句输出了内容。
go中的panic类似其它语言中的抛出异常,panic后面的代码不再执行(panic语句前面的defer语句会被执行)。
四、return 的实现逻辑
1、第一步给返回值赋值(若是有名返回值直接赋值,匿名返回值 则 先声明再 赋值) ;
2、第二步调用ret返回指令并传入返回值,ret会检查是否存在defer语句,若存 在就先逆序插播 defer语句 ;
3、最后 ret 携带返回值退出函数 。
可以看出 , return 不是一个原子操作,函数返回值与 ret 返回值并不一定一致。
五、defer、 return、返回值三者顺序
defer、 return、返回值 三者的执行顺序是 : return 最先给返回值赋值;接着 defer 开始执行一些收尾工作;最后 ret 指令携带返回值退出函数。
相关推荐:golang教程
以上就是go语言defer的用法是什么的详细内容。