golang defer实现

【Golang】defer的使用和底层实现 defer是Go语言的关键字,一般用于资源的释放和异常的捕捉(比如:文件打开、加锁、数据库连接、异常捕获) 阅读详情

golang defer实现

1.现象

  • defer 会在函数return前执行
  • 如果发生非系统级别panic,defer依然执行;在defer执行过程中,如果有recover,那就捕获panic,否则defer链调用结束,协程就GG
  • 如果发生系统级别异常(如panic during malloc)则直接退出进程不会执行任何defer函数
  • 多个defer倒序执行,类似栈
  • defer语句的参数,是立即评估,而不是等到执行时才评估

2.实现

  • defer是编辑器通过在函数开始、结束处插入特殊代码实现的,纯编译期行为
我们写的函数如下:
func A() {
    defer B()
    // A_logic_code
}
编译器给我们偷偷插入了2行(实际不止哈,简要示意)
func A() {
   r := deferproc(8, B) // 8是什么先不管,总之记住,这里叫注册defer
   // A_logic_code
   runtime.deferreturn() // 调用defer链
   return
}
通过这个示意伪代码,可以很清晰理解现象1、现象4

8 是函数B的参数和返回值空间大小之和,用于在A的栈上分配空间给defer
  • 再说现象3

    多个defer的时候,依次执行,每次都将一个defer结构体插入到defer链的链表头,所以执行的时候,就是倒序了

  • 再说非系统级别panic

    • 总原则:先触发非系统级别panic函数的执行,然后gopanic函数去调用defer函数,此时会一路传递panic信息,panic不会阻断defer执行
    • 如果一路在延迟函数中没有recover函数的调用,则会到达该携程的起点,该携程结束
    • 再说一个特例,panic1触发defer1函数,defer1函数有产生新的panic2,panic2又触发defer2函数,defer2函数又产生新的panic3

      Go的机制是如果当前defer函数是由之前的panic触发的并且当前defer函数会触发新的panic,则前一个panic停止执行,意思是本例,最终只能捕获到panic3,前两个被覆盖吞掉了

3.性能问题和优化

  • go1.12问题
    • defer在堆上分配,执行的时候,拷贝回栈
    • defer链表本就低效(执行过程中可能产生新的defer insert,执行时又delete)
  • go1.13减少堆栈拷贝

    • 把defer结构体定义在原函数内部,分配在栈上,然后注册的时候,指向栈内地址

      defer结构体增加一个字段heap标识是否为堆分配

    • 不适用于显示、隐式循环defer

    • 提升 约30%

  • go1.14优化

    • 函数内联展开:更狠,不再注册defer链,而是直接开始处插入defer函数所需的参数的变量定义,return插入显示defer函数的代码

      简单来说,就是直接把defer函数的逻辑代码拷贝,嵌套到原函数,再适当的补齐defer函数执行所需的形参

    • 不适用于显示、隐式循环defer

    • 提升一个数量级

Golang defer 的编译器实现细节 defer是Go语言中最具特色的语法之一,它通过“延迟执行”的机制简化了资源管理(如文件关闭、锁释放)、错误处理等场景的代码逻辑。但大多数开发者对defer编译器如何识别defer语句?defer的“后进先出”(LIFO)顺序是如何实现的?Go1.14之后的“开放编码优化”到底优化了什么?本文将围绕这些问题,从编译器前端(语法分析)到后端(代码生成),再到运行时(runtime)的完整链路展开解析。用生活案例解释defer的核心行为;拆解编译器如何将defer转换为中间代码; 阅读详情

相关推荐

Golang defer 与缓存管理的优雅实现

资源泄露(如忘记释放锁、未归还连接池资源)代码冗余(重复编写清理逻辑)本文将聚焦defer关键字如何化解这些问题,覆盖基础原理、实战技巧到生产级优化,适合从初级到中级的Golang开发者。本文将从defer的底层逻辑讲起,通过生活案例理解其核心价值;接着拆解缓存管理的常见痛点,结合defer设计解决方案;最后用完整项目实战演示如何实现一个线程安全的内存缓存。import ("sync""time"// 缓存项结构,包含值和过期时间。

AI Agent Harness Engineering 966

golang的defer机制详解

defer概述 defer用来声明一个延迟函数,把这个函数放入到一个栈上,当外部的包含方法return之前,返回参数到调用方法之前调用,也可以说是运行到最外层方法体时调用。我们经常用他来做一些资源的释放,比如关闭io操作。 defer是golang的一个特色功能,被称为“延迟调用函数”。当外部函数返回后执行defer。类似于其他语言的 try… catch … finally…...

zhongcanw的博客 5033

Docker一键部署Synopsys EDA全家桶(VCS/Verdi 2018版)保姆级教程

本文提供了一份详尽的Docker容器化部署Synopsys EDA工具链(VCS/Verdi 2018版)的保姆级教程。通过环境隔离与标准化,解决传统安装的依赖冲突问题,并重点攻克了容器内GUI图形界面显示的核心难题。教程涵盖从Docker基础安装、镜像获取、容器启动配置,到使用X11转发或VNC实现Verdi完美显示的完整实践,旨在帮助芯片设计工程师快速构建稳定、可移植的一键化EDA工作环境。

weixin_29281941的博客 198

Golang中的defer

目录Golang中的Defer必掌握的7知识点知识点1:defer的执行顺序知识点2:defer与return谁先谁后知识点3:函数的返回值初始化知识点4:有名函数返回值遇见defer情况知识点5:defer遇见panic知识点6:defer中包含panic知识点7:defer下的函数参数包含子函数 defer底层如何实现多个defer出现的时候,它是一个“栈”的关系,也就是先进后出。一个函数中,写在前面的defer会比写在后面的defer调用的晚。 测试代码: 执行结果: 知识点3:函数的返

qq2904529388的博客 2515

虚幻引擎5 AR开发教程02:构建和测试AR Android App

在本教程中,我们将学习如何在虚幻引擎 5 上构建和测试 AR 安卓应用。

mopanchun的博客 2650

Win10 环境下 ISE14.7 iMPACT 闪退的 DLL 修复方案 - FPGA 开发实战

本文详细介绍了在Win10系统下解决ISE14.7 iMPACT工具闪退问题的DLL修复方案,特别针对FPGA开发中常见的兼容性问题。通过替换关键DLL文件,有效解决了iMPACT在生成PROM文件时的崩溃问题,并提供了详细的步骤说明和注意事项,帮助开发者提升工作效率。

weixin_29197051的博客 210

golang——defer

defer是Go语言提供的一种用于注册延迟调用的机制,让函数或语句可以在当前函数执行完毕后(包括通过return正常结束或者panic导致的异常结束)执行。

weixin_45627369的博客 1115

MAPLAB X IDE仿真调试

一、开发环境 操作系统:Windows 10 调试工具:Pickit3 单片机型号:PIC24FJ32GA002 二、操作步骤 1、连接Pickit3仿真器于单片机对应的烧写口如图示: 2、点击调试项目进入调试模式,这时底下输出框显示"运行"代表成功进入调试模式。 3、选择断点,该IDE只支持两个断点,使用超过两个时,超过的断点亮灰色代表无效。设置好断点后需暂停然后再重新点击运行才能生效。可以看到在断点处有绿色光标。 ...

RealHero的博客 5084

GoLang之defer底层系列一(v 1.12)

GoLang之defer底层系列一(v 1.12)

weixin_52690231的博客 627

(2024,DDPM,DDIM,流匹配,SDE,ODE)扩散:基础教程

本文的目标是尽可能简单地教授扩散。第一节介绍扩散的基本原理。第二节和第三节展示如何构建随机和确定性扩散采样器。第四部分介绍了密切相关的流匹配,可看作是扩散的推广。​第五节,强调实践中最重要的一些设计选择,包括采样器、噪声时间表和参数化方法。

qq_44681809的博客 1万+

手把手教会你用yolov8从环境配置到检测任务实战

做本文章前,我浏览过很多网上资料,我发现他们总是写的含糊不清,而且实际操作起来就会有各种各样的问题,要么就是根本不适合一些小白,所以我在这里写一篇完全针对小白的yolo从入门到实战。看完本文章后大家都可以实现下图效果,数字识别是一种比较简单的检测任务,其他识别任务学完本例也能够一通百通,大家边做边学,更好的体会yolo的神奇之处。

KevenDuan的博客 2871

Go语言中 defer 的用法

Go语言中 defer 的用法使用中的一些坑

lp15929801907的博客 3742

保姆级避坑指南:Mid-360雷达到手后,用livox_ros_driver2从接线到出点云的完整流程

本文提供Mid-360雷达到手后的完整使用指南,涵盖从硬件接线、网络配置到livox_ros_driver2驱动的安装与调试,帮助用户避开常见陷阱,实现点云数据的稳定输出与可视化。重点解析了配置文件的参数设置和点云格式选择,确保用户能够高效部署和使用Mid-360雷达。

weixin_30733003的博客 484

【go】go中defer实现原理

deferdefer。

m0_74282926的博客 1293

《AgentScope-Java 深入浅出教程》第3章 消息系统(Message)

在 AgentScope 中,消息(Msg)是最核心的数据结构。│ 消息的作用 ││ ││ │ 用户输入 │ ────────────┐ ││ ▼ ││ │智能体通信│ ◄────► │ 消息对象 │ ◄────► │ LLM API │ ││ ▲ ││ │ ││ │ 历史存储 │ ────────────┘ ││ │用户输入:封装用户的问题和指令智能体输出:封装智能体的回复和工具调用智能体通信:在多智能体系统中传递信息LLM API 交互:转换为 LLM 可理解的格式历史存储。

步子哥的博客 228

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Golang中defer的实现原理

前言 在Go语言中,可以使用关键字defer向函数注册退出调用,即主函数退出时,defer后的函数才被调用。defer语句的作用是不管程序是否出现异常,均在函数退出时自动执行相关代码。 所以,defer后面的函数通常又叫做延迟函数 defer规则 1.延迟函数的参数在defer语句出现时就已经确定下来了 func a() { i := 0 defer fmt.Println(i) i++ return } 返回结果: defer语句中打印的变量i在defer出现时就已经拷

香烟,瓜子,矿泉水 1187

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C语言实现Go的defer功能

之前笔者写了一篇博文,介绍了如何在C++语言中实现Go的defer功能,那在C语言中是否也可以实现这样的功能呢?本文就将介绍一下如何在C语言中实现Go的defer功能。我们还是使用为了实现该功能,需要借助编译器的扩展功能,GCC/Clang的cleanup属性,微软目前的编译器不支持该扩展属性,所以本文介绍的方法不适用于微软编译器。

witton的专栏 1470

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Golang defer 关键字实现原理

这里写目录标题1. Golang defer 关键字实现原理1.1. 作用1.2. defer 的实现 1. Golang defer 关键字实现原理 1.1. 作用 defer 用于资源的释放, 会在函数返回之前进行调用。 如果有多个 defer 表达式, 调用顺序类似于栈, 越后面的 defer 表达式越先被调用。 defer 是在 return 之前执行的。这个在官方文档中是明确说明了的。要使用 defer 时不踩坑, 最重要的一点就是要明白, return xxx 这一条语句并不是一条原子指令! 函

云满笔记 281

Go defer实现原理剖析

1. 前言 defer语句用于延迟函数的调用,每次defer都会把一个函数压入栈中,函数返回前再把延迟的函数取出并执行。 为了方便描述,我们把创建defer的函数称为主函数,defer语句后面的函数称为延迟函数。 延迟函数可能有输入参数,这些参数可能来源于定义defer的函数,延迟函数也可能引用主函数用于返回的变量,也就是说延迟函数可能会影响主函数的一些行为,这些场景下,如果不了解defer...

Tybyqi的博客 2485

GO 中 defer的实现原理

文章目录GO 中 defer的实现原理defer 是什么?defer 实现原理咱们来画个图形象一点**咱一起来看看`defer` 的具体实现**`deferproc` 的作用是:咱看看 `deferproc` 的大体流程:最后再来看看`return0`简单说下 **deferreturn**GO 中 defer 的规则第一点咱们来写个小DEMO第三点也来一个DEMO总结欢迎点赞,关注,收藏 GO 中 defer的实现原理 我们来回顾一下上次的分享,分享了关于 通道的一些知识点 分享了 GO 中通道是什

m0_37322399的博客 453

Go defer(一):延迟调用的使用及其底层实现原理详解

defer是Go语言提供的一种用于注册延迟调用的机制,让函数或语句可以在当前函数执行完毕后(包括通过return正常结束或者panic导致的异常结束)执行。在资源释放、耗时统计等场景有着很高的使用频率。本文以Go 1.16版本的代码为例,主要介绍defer使用特点,其底层实现原理。

dahao_up39的博客 1456

Golang中defer关键字实现原理

defer和go一样都是Go语言提供的关键字。defer用于资源的释放,会在函数返回之前进行调用。一般采用如下模式: f,err := os.Open(filename) if err != nil { panic(err) } defer f.Close() 如果有多个defer表达式,调用顺序类似于栈,越后面的defer表达式越先被调用。 ...

skh2015java的博客 3147

C++ RAII实现golang的defer

在之前一篇文章<<从lock_guard来说一说C++中常用的RAII>> 讲解了RAII, 其实一种常见的资源管理方式,减少了资源泄露的风险。 同事和我说是不是就是智能指针, 准确来说RAII是一种思想,一般是利用栈上对象初始化进行资源的申请,在其生命周期结束的时候,自动调用其析构函数,对资源进行释放。 比如std::string, std::lock_guard都属于RAII的一种实现,那么对于不同资源的管理我是否都要实现一个类似于std::lock_guard一样的实现,其实不

一个程序员的修炼之路 878

Modern C++的应用,实现golang中的defer

modern C++ 实现 golang 中的 defer 语法。实现的过程用到了:lambda表达式、std::move、std::forward、右值引用、宏连接等比较绕一点的语法,没有了解过的读者可以先去了解一下这些语法。

冷山不生云 615
上一篇: golang T 和 *T的方法集是什么关系?
secretx
博客等级 码龄16年 72粉丝 75原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值