go语言defer的用法:1、defer语句在函数返回之前或函数中的return语句之后执行;2、多个defer语句的执行顺序是逆序执行;3、在panic语句后的defer语句不执行。

本文操作环境: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教程

更多相关文章

  1. 总结Golang实现PHP常用函数
  2. PHP扩展之XML操作(三)——XML解析器使用及相关函数
  3. 实例简析XPath串函数和XSLT
  4. XmlTextWriter函数定义与用法汇总
  5. XDocument函数定义与用法汇总
  6. 方式性能函数定义与用法汇总
  7. 用 await/async 正确链接 Javascript 中的多个函数[每日前端夜话
  8. 用原生 JavaScript 实现十大 jQuery 函数[每日前端夜话0x94]
  9. shell脚本之灵活调用函数技巧

随机推荐

  1. Android内存泄漏调试教程
  2. android stackView
  3. Android Hello World on IDEA
  4. Android TabHost风格
  5. Sending and receiving broadcast messag
  6. android 让自己的app成为launcher
  7. Android短信发送和监控
  8. Android的简单的广播的例子
  9. Android 101 for iOS Developers
  10. Android 各种机型兼容问题