go defer关键字使用规则
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关键字使用规则的更多相关文章
- go语言defer关键字背后的实现,语法,用法
原文: https://tiancaiamao.gitbooks.io/go-internals/content/zh/03.4.html ------------------------------ ...
- Swift - defer关键字(推迟执行)
在一些语言中,有try/finally这样的控制语句,比如Java. 这种语句可以让我们在finally代码块中执行必须要执行的代码,不管之前怎样的兴风作浪. 在Swift 2.0中,Apple提供了 ...
- 延宕执行,妙用无穷,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中defer关键字延迟调用机制使用EP17
先行定义,延后执行.不得不佩服Go lang设计者天才的设计,事实上,defer关键字就相当于Python中的try{ ...}except{ ...}finally{...}结构设计中的finall ...
- golang中defer的使用规则
转自个人博客chinazt.cc 在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函数正常返回,也就是return之后添加一个函数调用. ...
- [转]golang中defer的使用规则
转载于:https://studygolang.com/articles/10167 在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函 ...
- 并发编程之 Java 内存模型 + volatile 关键字 + Happen-Before 规则
前言 楼主这个标题其实有一种作死的味道,为什么呢,这三个东西其实可以分开为三篇文章来写,但是,楼主认为这三个东西又都是高度相关的,应当在一个知识点中.在一次学习中去理解这些东西.才能更好的理解 Jav ...
- Go语言之defer关键字
类似于java中的finally, 在函数返回来执行, 它用来保证函数一定会作一些事情. package main import "fmt" func main() { defer ...
- Go语言 关键字:defer
defer和go一样都是Go语言提供的关键字.defer用于资源的释放,会在函数返回之前进行调用.一般采用如下模式: f,err := os.Open(filename) if err != nil ...
- go中的关键字-defer
1. defer的使用 defer 延迟调用.我们先来看一下,有defer关键字的代码执行顺序: func main() { defer func() { fmt.Println("1号输出 ...
随机推荐
- anyRTC 6月SDK更新迭代
anyRTC 6月更新迭代,macOS新增屏幕 ID 进行屏幕共享功能,让共享更高效简单:此外解决了视频的宽高不是16:9导致共享内容缺失的问题,同时对音视频模块,推流组件等多项功能进行了优化改进. ...
- JMeter(1)-介绍+环境+安装+使用
一.开发接口测试案例的整体方案: 分析出测试需求,并拿到开发提供的接口说明文档: 从接口说明文档中整理出接口测试案例(包括详细的入参和出参数据以及明确的格式和检查点). 和开发一起对评审接口测试案例 ...
- Java Fork/Join
Fork/Join框架 Fork/Join 以递归方式将可以并行的任务拆分成更小的任务,然后将每个子任务的结果合并起来生成整体结果. 这个过程其实就是分治算法的并行版本,图解如下: 如何使用 我们要使 ...
- RHCSA_DAY09
常用特殊符号的使用 Linux系统下通配符起到了很大的作用,对于不确定的文档名称可以使用以下特殊字符表示 *常用的特殊符号,在文件名上,用来代表任意多个任意字符** ? 常用的特殊符号,在文件名上,用 ...
- Nacos 笔记
Nacos 笔记 目录 Nacos 笔记 1. Nacos简介 1.1 主流配置中心对比 1.2 主流注册中心对比 1.3 Nacos特性 2. 安装启动 支持外部 MySQL 3. 配置管理 3.1 ...
- Java8新特性(一)之Lambda表达式
.personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...
- kong整合Cosul实践(3)
1. 准备工作: 需要.netcore或者java程序一套,引入consul第三方包 我这里搭建了一个.netcore的webapi项目,引入Consul第三方包,网上可查资料一堆 环境需要kong, ...
- MaterialDesign Or ComboBox 联动查询
<ComboBox Width="200" Height="30" x:Name="ComboxName" Text="{B ...
- Shell-05-函数
函数 函数定义 shell中函数的定义格式如下 [ function ] funname [()] { action; [return int;] } 说明: 1.可以带function fun() ...
- Vue系列-05-项目2
路飞学城项目 调整首页细节 固定头部 App.vue <style> body{ padding: 0; margin:0; margin-top: 80px; } </style& ...