Go ---- defer 和 return 执行的先后顺序
Go 中 defer 和 return 执行的先后顺序
多个defer的执行顺序为“后进先出”;
defer、return、返回值三者的执行逻辑应该是:return最先执行,return负责将结果写入返回值中;接着defer开始执行一些收尾工作;最后函数携带当前返回值退出。
如果函数的返回值是无名的(不带命名返回值),则go语言会在执行return的时候会执行一个类似创建一个临时变量作为保存return值的动作,而有名返回值的函数,由于返回值在函数定义的时候已经将该变量进行定义,在执行return的时候会先执行返回值保存操作,而后续的defer函数会改变这个返回值(虽然defer是在return之后执行的,但是由于使用的函数定义的变量,所以执行defer操作后对该变量的修改会影响到return的值
eg1:不带命名返回值的函数
package main
import "fmt"
func main() {
fmt.Println("return:", test())// defer 和 return之间的顺序是先返回值, i=0,后defer
}
func test() int {//这里返回值没有命名
var i int
defer func() {
i++
fmt.Println("defer1", i) //作为闭包引用的话,则会在defer函数执行时根据整个上下文确定当前的值。i=2
}()
defer func() {
i++
fmt.Println("defer2", i) //作为闭包引用的话,则会在defer函数执行时根据整个上下文确定当前的值。i=1
}()
return i
}
test() 先返回 i=0
defer2先于defer1执行
输出结果为:
defer2 1
defer1 2
return: 0
eg2:带命名返回值的函数:
package main
import "fmt"
func main() {
fmt.Println("return:", test())
}
func test() (i int) { //返回值命名i
defer func() {
i++
fmt.Println("defer1", i)
}()
defer func() {
i++
fmt.Println("defer2", i)
}()
return i
}
对外部变量的引用作为函数参数(i),则在defer申明时就把值传递给defer,
输出结果为:
defer2 1
defer1 2
return: 2
理解return 返回值的运行机制:
为了弄清上述两种情况的区别,我们首先要理解return 返回值的运行机制:
return 并非原子操作,分为赋值,和返回值两步操作
eg1 : 实际上return 执行了两步操作,因为返回值没有命名,所以
return 默认指定了一个返回值(假设为s),首先将i赋值给s,后续
的操作因为是针对i,进行的,所以不会影响s, 此后因为s不会更新,所以
return s 不会改变
相当于:
var i int
s := i
return s
eg2 : 同上,s 就相当于 命名的变量i, 因为所有的操作都是基于
命名变量i(s),返回值也是i, 所以每一次defer操作,都会更新
返回值i
Go ---- defer 和 return 执行的先后顺序的更多相关文章
- go中defer的理解--defer、return、返回值之间执行顺序
defer可以读取有名返回值 func c() (i int) { defer func() { i++ }() return 1 } 输出结果是2. 在开头的时候,我们知道defer是在return ...
- Golang中defer、return、返回值之间执行顺序的坑
原文链接:https://studygolang.com/articles/4809 Go语言中延迟函数defer充当着 cry...catch 的重任,使用起来也非常简便,然而在实际应用中,很多go ...
- go defer、return的执行顺序
一.一个函数中多个defer的执行顺序 defer 的作用就是把defer关键字之后的函数执行压入一个栈中延迟执行,多个defer的执行顺序是后进先出LIFO,也就是先执行最后一个defer,最后执行 ...
- defer、return、返回值,这三者的执行逻辑
defer.return.返回值,这三者的执行逻辑是: return 最先执行,return 负责将结果写入返回值中:接着defer执行,可能修改返回值:最后函数携带当前返回值退出.
- finally return 执行顺序问题
网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下fina ...
- Swift - defer关键字(推迟执行)
在一些语言中,有try/finally这样的控制语句,比如Java. 这种语句可以让我们在finally代码块中执行必须要执行的代码,不管之前怎样的兴风作浪. 在Swift 2.0中,Apple提供了 ...
- 异常 try catch finally return 执行关系 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Vue中父子组件执行的先后顺序
Vera Vue中父子组件执行的先后顺序探讨(转载) 前几天,朋友向我提出了一个关于Vue中父子组件执行的先后顺序问题,相信很多朋友在学习的过程中也会遇到这个问题,所以我就在此提出我自己的一些小看 ...
- Vue中父子组件执行的先后顺序探讨
前几天,朋友向我提出了一个关于Vue中父子组件执行的先后顺序问题,相信很多朋友在学习的过程中也会遇到这个问题,所以我就在此提出我自己的一些小看法. 问题如下:请问下图中父子组件执行的先后顺序? 首先, ...
随机推荐
- nginx之echo模块与内置变量
Nginx扩展第三方模块——echo 第三方模块是对nginx的功能扩展,第三方模块需要在编译nginx的时候使用参数--add-module=PATH指定扩展模块的源码包路径给Nginx扩展添加ec ...
- 实现mysql的读写分离(mysql-proxy)____1(mysql的主从复制,基于gtid的主从复制,半同步复制,组复制)
主从复制原理: 从库生成两个线程,一个I/O线程,一个SQL线程: i/o线程去请求主库 的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中:主库会生成一个 log ...
- Flink入门介绍
什么是Flink Apache Flink是一个分布式大数据处理引擎,可以对有限数据流和无限数据流进行有状态计算.可部署在各种集群环境,对各种大小的数据规模进行快速计算. Flink特性 支持高吞吐. ...
- [Gamma]Scrum Meeting#3
github 本次会议项目由PM召开,时间为5月28日晚上10点30分 时长10分钟 任务表格 人员 昨日工作 下一步工作 木鬼 撰写博客,组织例会 撰写博客,组织例会 swoip 前端显示屏幕,翻译 ...
- MySQL 性能调优
MySQL 性能调优 索引 索引是什么 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里,不用一页一页查阅找出需要的资料. 索引目的 ...
- Dubbo Filter机制概述
https://blog.csdn.net/prestigeding/article/details/82085705 从上文可知,在服务的调用或消费端发送请求命令中,Dubbo引入过滤器链机制来实 ...
- MQTT研究之EMQ:【EMQX使用中的一些问题记录(3)】
EMQX功能强大,但是帮助信息或者可用资料的确有限,遇到个问题,比较难找到处理的头绪,今天,我要记录的是,使用中出现EMQX宕机,但是呢,启动也启动不了. 今天记录的内容,就以操作EMQX 3.2.3 ...
- centos6.10环境下启动多个redis实例
# 启动redis端口6379的配置 [root@newcms:/usr/local/nginx/conf]# /etc/redis.conf daemonize yes pidfile /usr/l ...
- python 一般处理
#!/usr/bin/env python# -*- coding:utf-8 -*-# Author:afei# QQ:97259460# date = 2019/8/29 s_code1=''s_ ...
- lamda表达式求最小值
//取最小设置金额的列 var minList = LsList.OrderBy(n=>n.Price).First(); //取最小设置金额的值 var minValue = LsList.S ...