defer

Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题。如下代码所示,我们一般写打开一个资源是这样操作的:

func ReadWrite() bool {file.Open("file")
// 做一些工作if failureX {file.Close()return false}if failureY {file.Close()return false}file.Close()return true
}

我们看到上面有很多重复的代码,Go的defer有效解决了这个问题。使用它后,不但代码量减少了很多,而且程序变得更优雅。在defer后指定的函数会在函数退出前调用。

func ReadWrite() bool {file.Open("file")defer file.Close()if failureX {return false}if failureY {return false}return true
}

如果有很多调用defer,那么defer是采用后进先出模式,所以如下代码会输出4 3 2 1 0

for i := 0; i < 5; i++ {defer fmt.Printf("%d ", i)
}

defer 给我的第一印象就是,类似java中的

try {

}finally {

}

我目前的理解就是,在函数块中使用defer,就是函数对应的有一个栈空间,先进后出。需要函数结束后调用栈,来出发defer操作。

如果,一个对象的创建,很消耗内存,需要及时关闭,defer无法像try finnaly哪样准确。

package mainimport "fmt"
import "time"type User struct {username string
}func (this *User) Close() {fmt.Println(this.username, "Closed !!!")
}func main() {u1 := &User{"jack"}defer u1.Close()u2 := &User{"lily"}defer u2.Close()time.Sleep(10 * time.Second)fmt.Println("Done !")}
[vicky@localhost goroutine]$

[vicky@localhost goroutine]$ go run deferTest1.go
Done !
lily Closed !!!
jack Closed !!!
[vicky@localhost goroutine]$

实际上,线程Sleep的10秒,u1,和u2早就可以Close()了,但却需要依赖main()函数的结束,才能defer执行。

那么尝试给defer添加内部代码区:

package mainimport "fmt"
import "time"type User struct {username string
}func (this *User) Close() {fmt.Println(this.username, "Closed !!!")
}func main() {{// 即便加了代码快范围,依旧也要主函数体结束才执行deferu1 := &User{"jack"}defer u1.Close()}u2 := &User{"lily"}defer u2.Close()time.Sleep(10 * time.Second)fmt.Println("Done !")}

Done !
lily Closed !!!
jack Closed !!!
[vicky@localhost goroutine]$

依旧defer的执行在Done!后。那么如何才能达到try finally 哪样准确的Close呢?

package mainimport "fmt"
import "time"type User struct {username string
}func (this *User) Close() {fmt.Println(this.username, "Closed !!!")
}func main() {u1 := &User{"jack"}f(u1) // 这样的方式,u1才会不依赖main函数的执行// 这样的方式,u2也不会依赖main函数的执行u2 := &User{"lily"}// m := func() {//         defer u2.Close()//         // u2 do somthing// }// m()
        func() {defer u2.Close()// u2 do somthing}()
        time.Sleep(10 * time.Second)        fmt.Println("Done !")}func f(u *User) {        defer u.Close()        // u1 do gomething}

[vicky@localhost goroutine]$ go run deferTest3.go
jack Closed !!!
lily Closed !!!
Done !

这样的使用方式,视乎不太合理,但却有存在的必要性。大多数情况下,可以用于 u1,u2  之类非常消耗内存,或者cpu,其后执行时间过程且没有太多关联的情况。既保留了defer的功能特性,也满足范围精确控制的条件!

go语言defer使用相关推荐

  1. Go语言defer详解笔记

    Go语言defer详解 1.defer概述: ​ defer是用来声明一个延迟函数,并且将这个函数放到一个栈中,它的调用时间在return执行之前,详细来讲,它的执行时间在return的值赋值之后,在 ...

  2. Go语言defer关键字

    Go语言的defer关键字用于延迟调用,下面是关于Go语言defer关键字的一些基础概念: 1. defer关键字用于注册延迟调用: 2. 这些调用直到包含当前该defer关键字的函数执行完了才会被执 ...

  3. Go语言 defer

    引言 Go 语言中的 defer 语句是 UNIX 之父 Ken Thompson 大神发明的,是完全正交的设计. 也正因为 Go 语言遵循的是正交的设计, 所以才有了: "少是指数级的多/ ...

  4. Go语言defer详解

    1. 使用defer的优势 defer一般用于资源的释放和异常的捕捉, 作为Go语言的特性之一. defer 语句会将其后面跟随的语句进行延迟处理. 意思就是说 跟在defer后面的语言 将会在程序进 ...

  5. go语言defer的作用

    1.第一种情况,.differ后面只能跟着函数调用逻辑,且是压栈操作,先入后出 如下代码: package mainimport "fmt"func main() {//go语言中 ...

  6. java怎么延迟执行语句_Go语言defer(延迟执行语句)

    Go语言中关键字defer允许我们推迟到函数返回之前(或任意位置执行return语句之后)一刻才执行某个语句或函数(为什么要在返回之后才执行这些语句?因为return语句同样可以包含一些操作,而不是单 ...

  7. Go 语言 defer recover panic 简单例子

    为什么80%的码农都做不了架构师?>>>    // Mydef project main.go package mainimport ("log" )func ...

  8. 万字长文剖析清楚 Go 语言 defer 原理

    大纲 编译器怎么编译 defer `struct _defer` 数据结构 `struct _defer` 内存分配 执行 defer 函数链( `deferreturn`  ) defer 怎么传递 ...

  9. go语言的defer语句

    go语言defer语句的用法 参考:https://www.jianshu.com/p/5b0b36f398a2 defer的语法 defer后面必须是函数调用语句,不能是其他语句,否则编译器会出错. ...

最新文章

  1. 思科CCIE认证知识点之IPv6地址
  2. char强制类型转换为int_C语言学习第5篇---类型转换概念理解
  3. 用 toto 3分钟建轻量级博客
  4. nodejs通过later实现定时执行任务
  5. MySQL数据库基础教程(视频)
  6. python爬取谷歌图片_Python爬取谷歌街景图片
  7. 建筑施工企业数字化安全质量监督管理系统
  8. 大数据告诉你,上海二手房到底难不难卖?
  9. 项目经理必须学会的财务知识
  10. SEO新手快速入门教程
  11. 计算机科学与技术审核评估专家,中国农业大学 业务动态 审核评估专家Sir Timothy深度走访网络技术中心...
  12. 在线pdf转epub网站
  13. Js 实现颜色值转换_Js 实现十六进制颜色值和RGB颜色值转换整理
  14. 华为nova7se乐活版和华为畅享20se 哪个好
  15. achb的c语言题目,C语言程序设题目及解答-09.doc
  16. 红队蓝队紫队具体是指什么
  17. 树莓派用默认账号和密码登录不上怎么办;修改树莓派的密码
  18. 通过Office 2007发布Blog
  19. 10 大趋势带你预见 DeFi 2020!
  20. 基于OpenCV2.4.x的SVM字符分类源码及其分析

热门文章

  1. 国学的天空-傅佩荣有声系列3
  2. 2020 | 带领团队学习成长,精华总结
  3. 斜抛运动的最大水平射程
  4. theBrain(思维导图工具)的使用知识浅析入门
  5. 均值滤波(Mean filtering)
  6. 手工AD Safe去广告教程
  7. 昆山市计算机培训机构哪里有,昆山靠谱的办公软件培训班在哪儿
  8. Linux中常用压缩、解压命令和压缩比率对比
  9. 2017——致自己内心走向“黑暗”的一年
  10. Java web图书管理系统——数据库课程设计