defer 作为延迟函数存在,在函数执行结束时才会正式执行,一般用于资源释放等操作

  参考一段代码https://mp.weixin.qq.com/s/yfH0CBnUBmH0oxfC2evKBA来分析defer 函数压栈操作

package def_test

import (
"fmt"
"testing"
) func GetFn() func() {
fmt.Println("outside")
return func() {
fmt.Println("Inside")
}
} func TestDefer(t *testing.T) {
defer GetFn()()
fmt.Println("Here")
}

  这里实际输出顺序为

outside
Here
Inside

按照代码执行顺序进行分析  

  1. "defer GetFn()()" 在执行这一行代码时,由于defer作为延迟函数存在独立的栈,需要将GetFn()()方法压入栈中,对于 GetFn()函数返回值也是一个函数,因此入栈的函数为GetFn()的返回值;
  2. 为了得到GetFn()的返回值,在defer入栈之前就已经开始执行了GetFn()方法,因此输出了"outside"
  3. 在执行完defer这一行时,继续往后执行"fmt.Println("Here")";
  4. 由于defer真正的执行是在函数返回之前进行调用,在函数返回之前会正式执行defer已入栈的全部方法,输出"Inside"

关于defer 延迟函数调用还有一个重要的点在于参数传递

  1. 对于引用类型传递没有太大的影响,栈中实际保存的是指针指向的地址
  2. 对于值类型数据传递,虽然defer是在函数正式返回前才正式执行调用,但由于其入栈操作是在执行到defer时就已经执行了,此时要传递的值已经复制,对于defer之后的代码对已传入值的数据操作实际是不会影响到defer真正执行时的数据

-------未完待续 剩余函数栈以及return分析

golang defer 以及 函数栈和return的更多相关文章

  1. golang之匿名函数结合defer

    defer语句中的函数会在return语句更新返回值变量后再执行,又因为在函数中定义的匿名函数可以访问该函数包括返回值变量在内的所有变量,所以,对匿名函数采用defer机制,可以使其观察函数的返回值. ...

  2. Golang基础之函数

    golang基础之函数 1.为什么需要函数? 有些相同的代码可能出现多次,如果不进行封装,那么多次写入到程序中,会造成程序冗余,并且可读性降低 2.什么是函数 为完成某些特定功能的程序指令集合称为函数 ...

  3. go 学习笔记之咬文嚼字带你弄清楚 defer 延迟函数

    温故知新不忘延迟基础 A "defer" statement invokes a function whose execution is deferred to the momen ...

  4. go 学习笔记之解读什么是defer延迟函数

    Go 语言中有个 defer 关键字,常用于实现延迟函数来保证关键代码的最终执行,常言道: "未雨绸缪方可有备无患". 延迟函数就是这么一种机制,无论程序是正常返回还是异常报错,只 ...

  5. golang defer那些坑

    defer以下几个特性,使用时需要关注下. 即时的参数传递 调用os.Exit()时defer不会被执行 defer与return的先后顺序 1.即时的参数传递 定义defer时传入的参数,是作为拷贝 ...

  6. golang defer 延后执行什么

    对于golang的defer,我们已经知道,defer定义的语句可以延后到函数返回时执行. 经常用在文件的关闭,锁的释放等场景中.而且defer定义的语句即使遇到panic也会执行.这样,可以执行必要 ...

  7. 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)

    这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...

  8. c函数调用过程原理及函数栈帧分析

    转载自地址:http://blog.csdn.net/zsy2020314/article/details/9429707       今天突然想分析一下函数在相互调用过程中栈帧的变化,还是想尽量以比 ...

  9. broadcom6838开发环境实现函数栈追踪

    在嵌入式设备开发中.内核为内核模块的函数栈追踪已经提供了非常好的支持,但用户层的函数栈追踪确没有非常好的提供支持. 在网上收集学习函数栈跟踪大部分都是描写叙述INTER体系架构支持栈帧的实现机制.或者 ...

随机推荐

  1. 5 个 Git 工作流,改善你的开发流程

    原文地址:5 Git workflows you can use to deliver better code and improve your development process 原文作者:Vi ...

  2. 安装pyspider报错:ERROR: Complete output from command python setup.py egg_info:...

    正在学习pyspider框架,安装过程并不顺利,随即百度了一下解决了问题,将解决方法记录备用 问题描述: 首先出现  pip版本低,根据提示升级即可 再次安装报错如下 解决过程: 第一步:首先安装wh ...

  3. linux 修改 mac

    ifconfig eth0 hw ether fa::3d:c3:: 或 ip link set dev eth0 address fa::3d:c3::

  4. Reinforcement Learning, Fast and Slow

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! 1 DeepMind, London, UK2 University College London, London, UK3 Prince ...

  5. Android中RecyclerView用法,一步一步教你如何使用RecyclerView以及带你走过编码中可能会出现的坑~

    首先,要明白RecyclerView是做什么的?其次是为什么要用RecyclerView?这里牵扯到RecyclerView和ListView的区别,这里不废话,大家自行百度即可! 以下示例我用的An ...

  6. instanceof判断问题

    有时候我们根据instanceof来判断对象的数据类型 但是 用instanceof判断基本数据类型时 会不靠谱 例如 let str = '123' let str1 = new String(&q ...

  7. Serializers组件详解

    Serializers组件 使用背景 因为每个语言都有自己的数据类型,不同语言要想数据传输,就必须指定一种各种语言通用的数据类型,如json,xml等等 序列化器允许把像查询集和模型实例这样的复杂数据 ...

  8. oeasy教您玩转linux-010110内容回顾

    我们来回顾一下 我们都讲了什么?

  9. Forward Rendering VS Deferred Rendering

    http://gad.qq.com/article/detail/32731 Forward Rendering Deferred Rendering

  10. JavaScript 时间都去那了(操作时间字符串加减时间)

    ---给时间充点时间吧--- 时间转换函数: function dateFormat(date, format) { date = new Date(date); var o = { 'M+': da ...