go defer (go延迟函数)
go defer (go延迟函数)
Go语言的defer算是一个语言的新特性,至少对比当今主流编程语言如此。根据GO LANGUAGE SPEC的说法:
A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking. defer语句调用一个函数,这个函数执行会推迟,直到外围的函数返回,或者外围函数运行到最后,或者相应的goroutine panic
换句话说,每当defer执行的时候,它后面的函数值(在go中函数是一个引用类型,是一等公民,可以赋值给变量)和函数参数会被求值,但是函数不会立即调用,直到(↑)上述三种情况发生。 这就是defer的全部内容,没了,剩下就是defer的best practice
函数不会立即调用
先从最简单的开始:
func readFile(fileName string){
f,err := os.Open(fileName)
if err!=nil {
return
}
defer f.Close()
var content [1024]byte
f.Read(content[:])
fmt.Printf("%s",content)
}
func main() {
readFile("test.data")
}
程序输出test.data前1024字节的内容。值得一提的是,类似这种open/close配对操作是defer的惯用法。 这个例子诠释了上面那句话的后半段
"但是函数不会被调用"
因为如果defer后面的f.Close()没有延迟执行,那么文件描述符都关闭了,就不会读取到任何内容。
函数值和函数参数被求值,但函数不会立即调用
下面这个例子即将诠释上半段,它来自<>,稍作修改:
func trace(funcName string) func(){
start := time.Now()
fmt.Printf("function %s enter\n",funcName)
return func(){
log.Printf("function %s exit (elapsed %s)",funcName,time.Since(start))
}
}
func foo(){
defer trace("foo()")()
time.Sleep(5*time.Second)
}
func main(){
foo()
foo()
}
/*
OUTPUT:
function foo() enter
function foo() exit (elapsed 5.0095471s)
function foo() enter
function foo() exit (elapsed 5.0005382s)
*/
为什么foo会输出enter然后等待五秒左右再输出exit? 因为正如我们说的,
defer后面的函数值和参数会被求值但是实际函数调用却要等到最后
这里函数值就是trace()返回的匿名函数,函数参数当然就是字符串字面值"foo()", 对trace("foo()")的求值会输出function foo() enter, 实际函数调用trace("foo()")()即输出function foo() exit(elapsed x.x)会推迟到return执行(如果return会更新返回值变量,则会在更新后才执行defer的函数)。
杂项
多说一点,如果存在多个defer语句,最后的defer的函数的执行顺序与defer出现的顺序相反,如:
func main() {
func1 := func(){
fmt.Println("func1() execution deferred")
}
func2 := func(){
fmt.Println("func2() execution deferred")
}
defer func1()
defer func2()
fmt.Println("strat\nworking...")
}
/*
OUTPUT:
strat
working...
func2() execution deferred
func1() execution deferred
*/
go defer (go延迟函数)的更多相关文章
- go 学习笔记之解读什么是defer延迟函数
Go 语言中有个 defer 关键字,常用于实现延迟函数来保证关键代码的最终执行,常言道: "未雨绸缪方可有备无患". 延迟函数就是这么一种机制,无论程序是正常返回还是异常报错,只 ...
- Go 延迟函数 defer 详解
Go 延迟函数 defer 详解 Go 语言中延迟函数 defer 充当着 try...catch 的重任,使用起来也非常简便,然而在实际应用中,很多 gopher 并没有真正搞明白 defer.re ...
- Golang入门教程(十三)延迟函数defer详解
前言 大家都知道go语言的defer功能很强大,对于资源管理非常方便,但是如果没用好,也会有陷阱哦.Go 语言中延迟函数 defer 充当着 try...catch 的重任,使用起来也非常简便,然而在 ...
- go 学习笔记之咬文嚼字带你弄清楚 defer 延迟函数
温故知新不忘延迟基础 A "defer" statement invokes a function whose execution is deferred to the momen ...
- GO语言延迟函数defer用法分析
这篇文章主要介绍了GO语言延迟函数defer用法,较为详细的分析了GO语言的特性与具体用法,并给出了一个比较典型的应用实例,具有一定的参考借鉴价值,需要的朋友可以参考下 本文实例讲述了GO语言延迟 ...
- Python也可以拥有延迟函数
延迟函数defer 我们知道在Golang中有一个关键字defer,用它来声明在函数调用前,会让函数*延迟**到外部函数退出时再执行,注意,这里的退出含义:函数return返回或者函数panic退出 ...
- Delphi 延迟函数 比sleep 要好的多
转自:http://www.cnblogs.com/Bung/archive/2011/05/17/2048867.html //延迟函数:方法一 procedure delay(msecs:inte ...
- 延迟函数 比sleep效果好
sleep是会阻塞线程的 网上有些延迟函数测试下来还是会阻塞,而接下来推荐的代码则不会 1 2 3 4 5 6 7 8 9 procedure delay(dwMilliseconds:integ ...
- C# 延迟函数
#region 延迟函数 public static bool Delay(int delayTime) { DateTime now = DateTime.Now; int s; do { Time ...
随机推荐
- auxblogcms1.0.6|代码审计
这周的审计任务,两天前的任务呀~拖延症呀~ 这次审计一个博客----auxblogcms1.0.6,网上也有所记载,我下面会做个总结. axublog是一款php个人博客系统,小巧强大的PHP+MyS ...
- eclipse环境下基于tomcat-7.0.82构建struts2项目
开山第一篇,毕业4个月目前接触最多的框架还是s2sh框架.... 具备完整的开发环境下,在eclipse下启动tomcat出现如下所示画面表示环境构建成功. 第一步:创建web项目,截图如下 此页面只 ...
- [搜索]ElasticSearch Java Api(一) -添加数据创建索引
转载:http://blog.csdn.net/napoay/article/details/51707023 ElasticSearch JAVA API官网文档:https://www.elast ...
- 【二十】mysqli基于面向过程与面向对象的编程
面向过程的方式 musqli扩展库操作mysql数据库步骤: 1.获取连接并选择数据库 //语法 mysqli_connect(host,username,password,dbname,port,s ...
- selenium定位tr及td,并获取其文本及属性
#获取所有的trtrlist=brower.find_elements_by_tag_name("tr")for tr in trlist: #获取tr中的所有td tdlist= ...
- 用Vim 加密文本
Vim强大就在于 可以干任何想要做的事情,比如加密.Fedora 18上给大家做一个测试.首先安装 vim: sudo yum install vim -y然后检验模块是否有加密: vim --ver ...
- Spring-MVC理解之一:应用上下文webApplicationContext
一.先说ServletContext javaee标准规定了,servlet容器需要在应用项目启动时,给应用项目初始化一个ServletContext作为公共环境容器存放公共信息.ServletCon ...
- 实时同步rsync+inotify
实时同步rsync+inotify 原创博文http://www.cnblogs.com/elvi/p/7658071.html #linux同步 #实时同步rsync+inotify,双向同步ino ...
- Vue.js学习 — 微信公众号菜单编辑器(一)
学习里一段时间Vue.js,于是想尝试着做一个像微信平台里那样的菜单编辑器,在这里分享下 具体样式代码查看项目github 创建一个vue实例 <!DOCTYPE html> <ht ...
- 百度编辑器的内容改变事件监听bug
先贴上我的初始化代码,可能是用法问题冤枉了百度编辑器,如果是我的用法有问题欢迎大侠们指正 <!DOCTYPE type> <html> <head> <met ...