golang中defer的详解 转自https://blog.csdn.net/skh2015java/article/details/77081250
Go里的defer很有用,尤其在很多执行模块化操作时,初始化时给各个需要执行的模块传入参数,但是这些参数有些事在模块执行过程中才赋值的。
这时候有了defer就不会把代码写的很凌乱。
Go的defer语句用来调度一个函数调用(被延期的函数),使其在执行defer的函数即将返回之前才被运行,被延期执行的函数,它的参数(包括接受者)实在defer执行的时候被求值的,而不是在调用执行的时候。也就是说被延期执行的函数的参数是按正常顺序被求值的。
defer会按逆序执行
defer是Go语言提供的关键字,常用来释放资源,会在函数返回之前进行调用。如果有多个defer表达式,调用顺序类似于栈,越后面的defer表达式越先被调用。defer 函数调用的执行时机是外层函数设置返回值之后, 并且在即将返回之前。
例1:
func main() {
for i:=0 ;i<5;i++{
defer fmt.Printf("%d",i)
fmt.Println("bbbbb")
}
fmt.Println("aaaaa")
}
执行结果:
bbbbb
bbbbb
bbbbb
bbbbb
bbbbb
aaaaa
43210
例2:
func trace(s string) string {
fmt.Println("entering:",s)
return s
}
func un(s string) {
fmt.Println("leaving:",s)
}
func a() {
defer un(trace("a"))
fmt.Println("in a")
}
func b() {
defer un(trace("b"))
fmt.Println("in b")
a()
}
func main() {
b()
}
执行结果如下:
entering: b
in b
entering: a
in a
leaving: a
leaving: b
例3
func f1() (result int) {
defer func() {
result++
}()
return 0
}
func f2() (r int) {
t := 5
defer func() {
t = t+5
}()
return t
}
func f3() (t int) {
t = 5
defer func() {
t = t+5
}()
return t
}
func f4() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
要使用defer不踩坑,最重要的一点就是明白,return xxx不是一条原子指令
函数返回的过程是这样子的:先给返回值赋值,然后调用defer表达式,最后才是返回到调用函数中。
defer表达式可能会在设置函数返回值之后,在返回到调用函数之前,修改返回值,使最终的函数返回值与你想象的不一致。
可以将return xxx改成
返回值=xxx
调用defer函数
空的return
例3可以改写成这样
func f11() (result int) {
result = 0 //先给返回值赋值
func(){ //再执行defer 函数
result++
}()
return //最后返回
}
func f22() (r int) {
t := 5
r = t //赋值指令
func(){ //defer 函数被插入到赋值与返回之间执行,这个例子中返回值r没有被修改
t = t+5
}
return //返回
}
func f33() (t int) {
t = 5 //赋值指令
func(){
t = t+5 //然后执行defer函数,t值被修改
}
return
}
func f44() (r int) {
r = 1 //给返回值赋值
func(r int){ //这里的r传值进去的,是原来r的copy,不会改变要返回的那个r值
r = r+5
}(r)
return
}
参考:《Effective Go》、《深入解析go内核实现》
golang中defer的详解 转自https://blog.csdn.net/skh2015java/article/details/77081250的更多相关文章
- golang语言并发与并行——goroutine和channel的详细理解(一) 转发自https://blog.csdn.net/skh2015java/article/details/60330785
如果不是我对真正并行的线程的追求,就不会认识到Go有多么的迷人. Go语言从语言层面上就支持了并发,这与其他语言大不一样,不像以前我们要用Thread库 来新建线程,还要用线程安全的队列库来共享数据. ...
- Window 对象详解 转自 http://blog.csdn.net/jcx5083761/article/details/41243697
详解HTML中的window对象和document对象 标签: HTMLwindowdocument 2014-11-18 11:03 5884人阅读 评论(0) 收藏 举报 分类: HTML& ...
- 28 Corn表达式详解 (转自http://blog.csdn.net/claram/article/details/51785193)
Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: Seconds Minutes Hours DayofMonth Month ...
- .net反射详解 原文://http://blog.csdn.net/wenyan07/article/details/27882363
概述反射 通过反射可以提供类型信息,从而使得我们开发人员在运行时能够利用这些信息构造和使用对象. 反射机制允许程序在执行过程中动态地添加各种功能. 运行时类型标识 运行时类型标识(RTTI),可以在程 ...
- springboot项目--传入参数校验-----SpringBoot开发详解(五)--Controller接收参数以及参数校验----https://blog.csdn.net/qq_31001665/article/details/71075743
https://blog.csdn.net/qq_31001665/article/details/71075743 springboot项目--传入参数校验-----SpringBoot开发详解(五 ...
- 虚拟机中的CentOS7如何上网?---https://blog.csdn.net/nothing2017/article/details/61420767
虚拟机中的CentOS7如何上网?https://blog.csdn.net/nothing2017/article/details/61420767
- Golang拼接字符串的5种方法及其效率_Chrispink-CSDN博客_golang 字符串拼接效率 https://blog.csdn.net/m0_37422289/article/details/103362740
Different ways to concatenate two strings in Golang - GeeksforGeeks https://www.geeksforgeeks.org/di ...
- 向txt文件中写入内容(覆盖重写与在末尾续写+FileOutputStream与FileWriter)(转发:https://blog.csdn.net/bestcxx/article/details/51381460)
!!!! 读取txt文件中的内容 import java.io.BufferedReader; import java.io.File; import java.io.FileReader; /** ...
- Redis中为什么使用跳表---------转自http://blog.csdn.net/u010412301/article/details/64923131
最近在研究数据库的一些底层实现,百度的面试官问到了跳表,当时没有回答上来,在csdn上看到了这篇文章,感觉写的比较好,希望大家可以多多交流. Redis里面使用skiplist是为了实现sorted ...
随机推荐
- sublime text3 key
Sublime Text 3 3126 注册码 第一个测试通过 —– BEGIN LICENSE —– Michael Barnes Single User License EA7E-821385 8 ...
- 【翻译】Context should go away for Go 2
2017/08/06 每次blog.golang.org更新博客,我都迫不及待去读一下:最新的一篇, Contributors Summit,记录了Go贡献者们的一些讨论.我读到一句话,让我感觉得 ...
- js获取当天零点的时间戳
var now_date = new Date();//获取Date对象now_date.setHours(0);//设置小时now_date.setMinutes(0);//设置分钟now_date ...
- Unescaped left brace in regex is illegal here in regex; marked by <-- HERE in m/\${ <-- HERE ([^ \t=:+{}]+)}/ at xxxx/usr/bin/automake line 3939.
/********************************************************************** * Unescaped left brace in re ...
- ERROR: gnu-config-native-20150728+gitAUTOINC+b576fa87c1-r0 do_unpack: Function failed: Fetcher failure: Fetch command failed with exit code 128, output: fatal: the '--set-upstream' option is no longer
/********************************************************************** * ERROR: gnu-config-native-2 ...
- 服务器上安装caffe的过程记录
1. 前言 因为新的实验室东西都是新的,所以在服务器上要自己重新配置CAFFE 这里假设所有依赖包学长们都安装好了,我是没有sudo权限的 服务器的配置: CUDA 8.0 Ubuntu 16.04 ...
- 质因子分解(Pollard_Rho法)
LL Pollard_Rho(LL n, LL c) { LL x, y, d; LL i = , k = ; x = y = rand() % n; do { i++; d = gcd(n + y ...
- L2-008 最长对称子串 (25 分)
对给定的字符串,本题要求你输出最长对称子串的长度.例如,给定Is PAT&TAP symmetric?,最长对称子串为s PAT&TAP s,于是你应该输出11. 输入格式: 输入在一 ...
- 《DSP using MATLAB》Problem 5.24-5.25-5.26
代码: function y = circonvt(x1,x2,N) %% N-point Circular convolution between x1 and x2: (time domain) ...
- 走进 AQS 瞧一瞧看一看
并发中有一块很重要的东西就是AQS.接下来一周的目标就是它. 看复杂源码时,一眼望过去,这是什么?不要慌,像剥洋葱一样,一层层剥开(哥,喜欢"扒开"这个词). 参考资源: http ...