2020-11-19:go中,defer原理是什么?
福哥答案2020-11-19:
- - 什么是defer
- defer是go语言提供的一种用于注册延迟调用的机制:让函数或者语句在当前函数执行完毕(包括return正常结束或者panic导致的异常结束)之后执行。
- defer语句通常用于一些成对的操作场景,打开/关闭连接,加锁/解锁,打开文件/关闭文件等等
- defer在一些需要回收资源的场景中非常有用
- 为什么需要defer
- 有效防止内存泄漏
- defer底层原理
- 每次defer语句在执行的时候,都会将函数进行“压栈”,函数参数会被拷贝下来。当外层函数退出时,defer函数会按照定义的顺序逆序执行。如果defer执行的函数为nil,那么会在最终调用函数中产生panic。
- 编译器会把 defer 语句翻译成对 deferproc 函数的调用,同时,编译器也会在使用了 defer 语句的 go 函数的末尾插入对 deferreturn 函数的调用。
- 每一个goroutine结构体中都有一个_defer 指针变量用来存放defer单链表。defer保存用什么数据结构?回答栈过不了面试官那关,defer单链表应该能过关。_defer 结构体如下:
- siz:所有传入参数的总大小。
- started:该 defer 是否已经执行过。
- heap:表明该defer是否存储在heap上。
- sp:函数栈指针寄存器,一般指向当前函数栈的栈顶。
- pc:程序计数器,有时称为指令指针(IP),线程利用它来跟踪下一个要执行的指令。在大多数处理器中,PC指向的是下一条指令,而不是当前指令。
- fn:指向传入的函数地址和参数。
- _panic:指向 _panic 链表。
- link:指向 _defer 链表。
- 为什么defer要按照定义的顺序逆序执行:后面定义的函数可能会依赖前面的资源,所以要先执行。如果前面先执行,释放掉这个依赖,那后面的函数就不能找到它的依赖了。
- defer函数定义时,对外部变量的引用方式有两种,分别是函数参数以及作为闭包引用。在作为函数参数的时候,在defer定义时就把值传递给defer,并被cache起来。如果是作为闭包引用,则会在defer真正调用的时候,根据整个上下文云确定当前的值。
- defer后面的语句在执行的时候,函数调用的参数会被保存起来,也就是复制一份。在真正执行的时候,实际上用到的是复制的变量,也就是说,如果这个变量是一个“值类型”,那他就和定义的时候是一致的,如果是一个“引用”,那么就可能和定义的时候的值不一致
- 利用defer原理
- 利用defer先求值,再延迟调用的性质
- defer与return
- defer语句的参数
- defer语句表达式的值在定义的时候就已经确定了
- 闭包:由函数以及相关引用环境组合而成的实例,也就是说闭包=函数+引用环境
- 匿名函数:匿名函数就是我们说的闭包,它不能独立存在,但可以直接调用或者赋值于某个变量。一个闭包,继承了函数声明时的作用域。在go语言中,所有的匿名函数都是闭包
- defer配合recover
- recover:异常捕获,可以让程序在引发panic的时候不会崩溃退出。在引发panic的时候,panic会停掉当前正在执行的程序,但是,在这之前,它会有序的执行完当前goroutine的defer列表的语句。所以我们通常在defer里面挂一个recover,防止程序直接挂掉,类似于try...catch.recover()函数只在defer的上下文中才有效,直接调用,会返回nil
***
[评论,有好几个参考地址](https://user.qzone.qq.com/3182319461/blog/1605740826)
2020-11-19:go中,defer原理是什么?的更多相关文章
- 2018.11.19 Struts2中Action类的书写方式
方式1: 方式2: 方式3
- 布客·ApacheCN 编程/后端/大数据/人工智能学习资源 2020.11
公告 我们始终与所有创作者站在一起,为创作自由而战.我们还会提供一切必要的技术支持. 我们全力支持科研开源(DOCX)计划.希望大家了解这个倡议,把这个倡议与自己的兴趣点结合,做点力所能及的事情. 我 ...
- Notes of Daily Scrum Meeting(11.19)
Notes of Daily Scrum Meeting(11.19) 现在工程项目进入尾声了,我们的项目中还有一些问题需要解决,调试修改起来进度比较慢,所以昨天就没有贴出项目 进度,今天的团队工作总 ...
- Linux中LVM2原理及制作LVM2
Linux中LVM2原理及制作LVM2 一.LVM原理 [MD]:Multi Device 多设备 Mdadm是一个用户空间工具,是RAID的管理工具,与真正的RAID工作没有太大关系.真正的RAID ...
- Linux编译内核 Ubuntu18.04 -2020.11.04
Linux编译内核 Ubuntu18.04 -2020.11.04 关闭虚拟机并备份 首先关闭虚拟机,其次直接找到.vmdk所在目录,并压缩该目录实现备份 下载内核源码 Linux内核官网:https ...
- apiAutoTest-更新2020/11/23
原始版本 简书:https://www.jianshu.com/p/6bfaca87a93b 博客园:https://www.cnblogs.com/zy7y/p/13426816.html test ...
- Goland 2020.2.x 激活码永久破解教程 (最新Goland激活码!2020.11.26亲测可用!)
在2020.11.26 Goland的用户们又迎来了一次更新,这就导致很多软件打开时候就提示Goland激活码已经失效,码小辫第一时间给各位分享了关于最新Goland激活破解教程! goland已经更 ...
- 2020.11最新JAVA环境安装配置
Windows10下java环境配置 更新:2020年11月25日 电脑环境: windows10 64位 一.下载jdk 首先到Oracle网站下载对应操作系统的jdk安装包. https://ww ...
- 智能物联网(AIoT,2020年)(中)
智能物联网(AIoT,2020年)(中) 05 中国AIoT产业图谱 06 中国AIoT商业模式 标准程度越低人力和时间成本投入越多,2B2C模式附加值高 07 中国AIoT玩家分布简介 四类玩家,优 ...
- 2. Go中defer使用注意事项
1. 简介 defer 会在当前函数返回前执行传入的函数,它会经常被用于关闭文件描述符.关闭数据库连接以及解锁资源. 理解这句话主要在三个方面: 当前函数 返回前执行,当然函数可能没有返回值 传入的函 ...
随机推荐
- FPGA实现国密算法SM4
本文基于FPGA实现高速SM4加密与解密,提供开源Verilog RTL设计和可综合工程:https://github.com/cassuto/SM4-FPGA. 本文仅讨论实现细节,不涉及算法原理. ...
- Winhex 恢复三个分区
通过之前的博客WinHex恢复分区,我们知道 在MBR中,一共有四行是我们分区的引导,所以,我们手动只能创建三个主分区,通过工具软件,我们最多可以创建四个主分区 那么测试:如何创建四个主分区? 首先, ...
- JavaWeb学习笔记第二弹
(续集)DQL:查询操作 1.排序查询 排序方式:(仅有一个排序参照时) 1.升序:ASC(默认) 命令:**select * from 表名 order by 列名 (asc);** 2.降序:DE ...
- Android--观察APP运行日志以及APP的工程目录结构解释
运行日志 Log:d--便于跟踪调试 APP开发基础 APP的运行环境 第一种情况,就是在Android studio软件客户端上面使用模拟器运行APP 第二种情况,就是使用真实的手机运行APP程序 ...
- MySQL学习(九)frm与ibd了解
参考:https://cloud.tencent.com/developer/article/1533746 InnoDB: frm,ibd MyISAM: frm,myd,myi ibd是InnoD ...
- Scanner基础用法
Scanner基础用法 引入包java.util.Scanner 读一个单词 package charpter2; import java.util.Scanner; public class Sca ...
- Module not found: Error: Can't resolve 'pubsub-js'
包未安装或者包版本过新,再者安装位置有误. 我安装各种工具库或者其他包时有个 -g 到全局的习惯,觉得装到全局时在文件夹中何时何处都可以用. 在子孙文件夹中引入时依赖会在子孙和文件根目录的node_m ...
- C/C++ 恨透了 double free or corruption
*以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「ENG八戒」https://mp.weixin.qq.com/s/IwSVImp5cOB3gZbaf0YiPw 写过 C/C++ 的都 ...
- JAVA基础——常用类(一)
首先认识到--String是不可以变性(final) String:字符串,使用一对""引起来表示. * 1.String声明为final的,不可被继承 * ...
- java -- Object类和String类
Object类 java.lang.Object类是Java语言中的根类,每个类都使用 Object 作为超类, 所有的类都直接或间接继承自 Object 类.所有对象(包括数组)都实现这个类的方法. ...