defer

用于延迟函数的调用,每次defer都会把一个函数压入栈中,函数返回前再把延迟的函数取出并执行

数据结构

type _defer struct {
sp uintptr //函数栈指针
pc uintptr //程序计数器
fn *funcval //函数地址
link *_defer //指向自身结构的指针,用于链接多个defer
}

规则一:延迟函数的参数在defer语句出现时就已经确定下来了

如:

func a() {
i := 0
defer fmt.Println(i)
i++
return
}

defer语句中的fmt.Println()参数i值在defer出现时就已经确定下来,实际上是拷贝了一份。后面对变量i的修改不会影响fmt.Println()函数的执行,仍然打印”0”。但是注意 这里对于指针类型参数,仍然适用,所以defer后面的语句对变量修改还是会影响延迟函数如:

func a() {
i := []int{1,2,3}
defer fmt.Println(i)
i[0]=10
return
}//会输出[10,2,3],因为这里i为指针,是数组的地址

规则二:先进后出

很好理解,延迟函数执行按先进后出顺序执行,即先进去的defer最后执行

规则三:延迟函数可能操作主函数的具名返回值

defer可能会改变返回值,因为return语句不是原子的,实际执行为设置返回值-->ret

defer语句实际执行在返回前,即拥有defer的函数返回过程是:设置返回值–>执行defer–>ret。

注意:这里返回值必须要有具体名字

如下:

func deferFuncReturn() (result int) {
i := 1 defer func() {
result++
}() return i
}

输出2,return语句先把result设置为i的值,即1,defer语句又把result递增1,所以最终返回2

如果返回的是匿名变量,则不改变,如:

func foo() int {
var i int i=1
defer func() {
i++
}() return i
}

这里还是返回1,上面的返回语句可以拆分成以下过程:

t=i	//t就是要返回的值
i++
return //返回t,这里t还是1

go defer关键字使用规则的更多相关文章

  1. go语言defer关键字背后的实现,语法,用法

    原文: https://tiancaiamao.gitbooks.io/go-internals/content/zh/03.4.html ------------------------------ ...

  2. Swift - defer关键字(推迟执行)

    在一些语言中,有try/finally这样的控制语句,比如Java. 这种语句可以让我们在finally代码块中执行必须要执行的代码,不管之前怎样的兴风作浪. 在Swift 2.0中,Apple提供了 ...

  3. 延宕执行,妙用无穷,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中defer关键字延迟调用机制使用EP17

    先行定义,延后执行.不得不佩服Go lang设计者天才的设计,事实上,defer关键字就相当于Python中的try{ ...}except{ ...}finally{...}结构设计中的finall ...

  4. golang中defer的使用规则

    转自个人博客chinazt.cc 在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函数正常返回,也就是return之后添加一个函数调用. ...

  5. [转]golang中defer的使用规则

    转载于:https://studygolang.com/articles/10167 在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函 ...

  6. 并发编程之 Java 内存模型 + volatile 关键字 + Happen-Before 规则

    前言 楼主这个标题其实有一种作死的味道,为什么呢,这三个东西其实可以分开为三篇文章来写,但是,楼主认为这三个东西又都是高度相关的,应当在一个知识点中.在一次学习中去理解这些东西.才能更好的理解 Jav ...

  7. Go语言之defer关键字

    类似于java中的finally, 在函数返回来执行, 它用来保证函数一定会作一些事情. package main import "fmt" func main() { defer ...

  8. Go语言 关键字:defer

    defer和go一样都是Go语言提供的关键字.defer用于资源的释放,会在函数返回之前进行调用.一般采用如下模式: f,err := os.Open(filename) if err != nil ...

  9. go中的关键字-defer

    1. defer的使用 defer 延迟调用.我们先来看一下,有defer关键字的代码执行顺序: func main() { defer func() { fmt.Println("1号输出 ...

随机推荐

  1. Maven BOM!拿来吧你

    what BOM? BOM(Bill of Materials)是由Maven提供的功能,它通过定义一整套相互兼容的jar包版本集合, 使用时只需要依赖该BOM文件,即可放心的使用需要的依赖jar包, ...

  2. vue3如何编写挂载DOM的插件

    vue3 跟 vue2 相比,多了一个 app 的概念,vue3 项目的创建也变成了 // main.jsimport { createApp } from 'vue' import App from ...

  3. vue(24)网络请求模块axios使用

    什么是axios Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 主要的作用:axios主要是用于向后台发起请求的,还有在请求中做更多是可控功能. a ...

  4. Deepin 20.2.2 /UOS 20.2 添加ppa源

    由于 工作需要,需要通过PPA安装一些优质的软件包,但是 Deepin 默认不支持PPA源 解决方法 由于Deepin/Uos系统默认是没有安装PPA的那么我们得先安装PPA来支持"add- ...

  5. python 环境遇到的报错

    pipenv install -r requirements.txt 时遇到错误: `Command "python setup.py egg_info" failed with ...

  6. 用 JavaScript 刷 LeetCode 的正确姿势【进阶】

    之前写了篇文章 用JavaScript刷LeetCode的正确姿势,简单总结一些用 JavaScript 刷力扣的基本调试技巧.最近又刷了点题,总结了些数据结构和算法,希望能对各为 JSer 刷题提供 ...

  7. Django debug page XSS漏洞(CVE-2017-12794)

    影响版本:1.11.5之前的版本 访问http://your-ip:8000/create_user/?username=<script>alert(1)</script>创建 ...

  8. 小技巧 | Get 到一个 Web 自动化方案,绝了!

    1. 前言 大家好,我是安果! 无论是 Chrome,还是 Firefox 浏览器,它们的强大性在很大程度上都是依赖于海量的插件,让我们能高效办公 那我们是否可以编写一个插件,让浏览器自动化完成一些日 ...

  9. Ghost ,博客系统代名词

    Ghost 博客系统是前 WordPress 的一些优秀员工的创业项目.项目仍然采用 100% 开源,加上官方的收费托管的商业模式,目前已经发展成为一个非常的博客系统. 为了更好的方便读者理解 Gho ...

  10. DL基础补全计划(五)---数值稳定性及参数初始化(梯度消失、梯度爆炸)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...