Golang-Defer

简介: Golang-Defer

defer触发时机


A “defer” statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.


Go官方文档中对defer的执行时机做了阐述,分别是。


  • 包裹defer的函数返回时


  • 包裹defer的函数执行到末尾时


  • 所在的goroutine发生panic时


defer执行顺序


当一个方法中有多个defer时, defer会将要延迟执行的方法“压栈”,当defer被触发时,将所有“压栈”的方法“出栈”并执行。所以defer的执行顺序是LIFO的。


执行顺序如下


# 常规执行语句1 -> 语句2 -> 语句3 -> 语句4# 在语句2,语句3中添加defer后执行顺序如下语句1 -> 语句4 -> 语句3(带defer) -> 语句2(带defer)


defer示例


package mainimport "fmt"func main() {
    d()
}func d() {
    fmt.Print("start" + "  ")
    fmt.Print("processing1" + "  ")
    fmt.Print("processing2" + "  ")
    fmt.Print("end" + "  ")
}


  • 没有defer:


start  -> processing1  ->  processing2  -> end


  • processing1、processing2 加入defer:


start  -> end  -> processing2  -> processing1


defer使用规则


defer会实时解析参数


package mainimport "fmt"func main() {
    i := 0
    defer fmt.Println(i)
    i ++    return}// 0


这是因为虽然我们在defer后面定义的是一个带变量的函数: fmt.Println(i). 但这个变量(i)在defer被声明的时候,就已经确定其确定的值了


defer的类栈执行


栈:先入后出


package mainimport "fmt"func f1()  {
    fmt.Println(1)
}func f2()  {
    fmt.Println(2)
}func main() {    defer f1()
    f2()
}// 2\1


defer可以读取有名返回值


func c() (i int) {   defer func() { i++ }()   return 1}func main()  {
   fmt.Println(c())
}// 2


在开头的时候,我们说过defer是在return调用之后才执行的。这里需要明确的是defer代码块的作用域仍然在函数之内,结合上面的函数也就是说,defer的作用域仍然在c函数之内。因此defer仍然可以读取c函数内的变量(如果无法读取函数内变量,那又如何进行变量清除呢…)。


当执行return 1 之后,i的值就是1. 此时此刻,defer代码块开始执行,对i进行自增操作。因此输出2.

目录
相关文章
|
SQL 关系型数据库 MySQL
如何使用MySQL Binlog Digger 4.14对binlog日志进行挖掘分析以便快速恢复误删除数据
MySQL Binlog Digger是一款运行在windows操作系统的挖掘与分析MySQL binlog的可视化工具,通过它可以快速打回被误操作时的数据,例如:delete, insert, update操作,并依据这些误操作生成相应的undo回滚语句,以便快速恢复数据,此外,它还可以支持离线binlog挖掘分析与binlog下载,它仅支持dml操作的回滚,但不支持ddl的回滚。
5051 1
如何使用MySQL Binlog Digger 4.14对binlog日志进行挖掘分析以便快速恢复误删除数据
|
缓存 安全 Java
Spring Get请求 与post请求
本文详细介绍了Spring框架中GET请求和POST请求的区别及应用场景。GET请求用于从服务器获取资源,参数附在URL末尾,适合查看非敏感信息;POST请求用于向服务器提交数据,参数在请求体中传输,适合处理敏感信息。Spring通过`@GetMapping`和`@PostMapping`注解分别处理这两种请求。此外,文章还提供了示例代码,展示了如何在Spring中实现这两种请求的处理。最后,文章总结了推荐使用POST请求的原因,包括更高的安全性、更大的数据传输量、更好的幂等性及灵活性。
533 1
Spring Get请求 与post请求
|
XML JSON Java
深入解析 Java @RestController 注解:构建现代化的RESTful API
在当今的Web应用开发中,RESTful API已成为连接前后端的重要桥梁。为了更方便地构建满足RESTful架构风格的API,Spring框架引入了 @RestController 注解,使得构建和管理API更加高效和简单。本文将带您深入了解 @RestController 注解,探讨其特点、用法、实现方式以及在实际应用中的优势。
|
Python
Python:utc时间转东八区北京时间astimezone
Python:utc时间转东八区北京时间astimezone
382 0
|
前端开发 JavaScript 程序员
数值的整数次方
数值的整数次方
数值的整数次方
|
安全 Linux 网络安全
个人博客刚部署,隔壁开发还没开始馋,就有人来撬门(上)
本文专门用于记录服务器运行过程中遇到的 安全问题及应对之法。
210 0
|
JavaScript
vue在渲染数组时for和splice的坑 实例为:删除所有选中的多选框对应的值
vue在渲染数组时for和splice的坑 实例为:删除所有选中的多选框对应的值
|
弹性计算 大数据 Linux
如何选择阿里云服务器相关配置
简介: 什么配置的阿里云服务器是适合自己的呢?下面我们就来说说如何选择阿里云服务器配置。
如何选择阿里云服务器相关配置
|
负载均衡 网络协议 Java
基于Docker部署 Tomcat集群、 Nginx负载均衡
当作一百世一样。这里的道理很明白:我思故我在,既然我存在,就不能装作不存在。无论如何,我要为自己负起责任。——王小波《三十而立》
579 0
基于Docker部署 Tomcat集群、 Nginx负载均衡
|
存储 NoSQL Java
Redis持久化深入理解
Redis持久化深入理解