原址

生命不止,继续 go go go !!!

学习golang这么久了,还没看到类似传统的 try…catch…finally 这种异常捕捉方式。 
但是,Go中引入的Exception处理:defer, panic, recover。

那么今天跟大家分享一下golang中的defer。闲言少叙,看一下defer的作用:

Defer is used to ensure that a function call is performed later in a program’s execution, usually for purposes of cleanup. defer is often used where e.g. ensure and finally would be used in other languages.

defer的思想类似于C++中的析构函数,不过Go语言中“析构”的不是对象,而是函数,defer就是用来添加函数结束时执行的语句。注意这里强调的是添加,而不是指定,因为不同于C++中的析构函数是静态的,Go中的defer是动态的。

引自:http://www.cnblogs.com/ghj1976/archive/2013/02/11/2910114.html

说多无用,想来个开胃菜,看看如何使用:

package mainimport "fmt"func main() {defer goodbye()defer goodnight()fmt.Println("Hello world.")
}func goodnight() {fmt.Println("GoodNight")
}func goodbye() {fmt.Println("Goodbye")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

输出: 
Hello world. 
GoodNight 
Goodbye

看出什么了吗? 
**defer在函数结束之前执行 
多个defer的执行顺序: Multiple defers are stacked last-in first-out so that the most recently deferred function is run first.**

那么defer之前就return了呢?

package mainimport "fmt"func main() {fmt.Println("Hello world.")returndefer goodbye()defer goodnight()
}func goodnight() {fmt.Println("GoodNight")
}func goodbye() {fmt.Println("Goodbye")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

输出: 
Hello world. 
defer是在return之前执行的

defer用于关闭文件

package mainimport "fmt"
import "os"func main() {f := createFile("/tmp/defer.txt")defer closeFile(f)writeFile(f)
}func createFile(p string) *os.File {fmt.Println("creating")f, err := os.Create(p)if err != nil {panic(err)}return f
}func writeFile(f *os.File) {fmt.Println("writing")fmt.Fprintln(f, "data")}func closeFile(f *os.File) {fmt.Println("closing")f.Close()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

defer用于锁

func Divide(i int) error {mu.Lock()defer mu.Unlock()if i == 0 {return errors.New("Can't divide by zero!")}val /= ireturn nil
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

defer中的坑儿

看下面的代码:

package mainimport ("fmt"
)func main() {fmt.Println(f())fmt.Println(f1())fmt.Println(f2())
}func f() (result int) {defer func() {result++}()return 0
}func f1() (r int) {t := 5defer func() {t = t + 5}()return t
}func f2() (r int) {defer func(r int) {r = r + 5}(r)return 1
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

输出: 


1

要使用defer时不踩坑,最重要的一点就是要明白,return xxx这一条语句并不是一条原子指令! 
函数返回的过程是这样的:先给返回值赋值,然后调用defer表达式,最后才是返回到调用函数中。 
defer表达式可能会在设置函数返回值之后,在返回到调用函数之前,修改返回值,使最终的函数返回值与你想象的不一致。 
出自:https://tiancaiamao.gitbooks.io/go-internals/content/zh/03.4.html

Go实战--golang中defer的使用相关推荐

  1. Go实战--golang中使用echo框架中JSONP(labstack/echo)

    生命不止,继续 go go go !!! 继续,echo web框架,今天就聊一聊JSONP. JSONP 1.什么是JSONP? JSONP (JSON with padding) is used ...

  2. Go实战--golang中OAuth2.0的使用(使用google账号进行登陆验证)

    生命不止,继续 go go go!!! 今天继续分享golang中的认证问题,之前写过两篇: 一篇是关于basic认证:Go实战–通过basic认证的http(basic authentication ...

  3. Go实战--golang中操作PDF(rsc.io/pdf、jung-kurt/gofpdf、signintech/gopdf)

    生命不止,继续 go go go !!! 昨天介绍了golang中如何操作excel: Go实战–golang中操作excel(tealeg/xlsx.360EntSecGroup-Skylar/ex ...

  4. Go实战--golang中使用echo框架、MongoDB、JWT搭建REST API(labstack/echo、gopkg.in/mgo.v2、dgrijalva/jwt-go)

    生命不止,继续go go go !!! 之前介绍过golang中restful api的博客,是使用redis作为持久化,httprouter作为框架: Go实战–通过httprouter和redis ...

  5. Go实战--golang中使用redis(redigo和go-redis/redis这个已测试)

    自己做测试了没有问题,虚拟机连不上可以把包下载到本地. 版权声明:本文为博主原创文章,未经博主允许不得转载. http://blog.csdn.net/wangshubo1989/article/de ...

  6. Go实战--golang中使用JWT(JSON Web Token)

    生命不止,继续 go go go !!! 之前写过关于golang中如何使用cookie的博客: 实战–go中使用cookie 今天就来跟大家简单介绍一下golang中如何使用token,当然是要依赖 ...

  7. Go实战--golang中使用gRPC和Protobuf实现高性能api(golang/protobuf、google.golang.org/grpc)

    生命不止,继续 go go go !!! 号外号外,插播一条广告,通过博客的uv可以看到周五,程序员是不怎么干活的: 本篇博客,使用gRPC和Protobuf,实现所谓的高性能api. protobu ...

  8. Go实战--golang中使用号称全世界最快的JSON解析器json-iterator(json-iterator/go)

    生命不止,继续go go go!!! 号外号外,差不一条广告,我的博客六月到十一月UV的地域分布: golang中的使用json一点也不陌生,golang为我们提供了官方的encoding/json: ...

  9. Go实战--golang中使用redis(redigo和go-redis/redis)

    生命不止,继续 go go go !!! 以前介绍过golang中如何使用sqlite3: <Go实战–go语言操作sqlite数据库(The way to go)> 今天跟大家分享的是如 ...

最新文章

  1. 这是时间的推移 不是系统的分类
  2. 内存不足 java.lang.OutOfMemoryError: Java heap space
  3. 发现还是 True Image Server v8.1.941 比较好用
  4. win8 打开计算机配置,win8.1 更改电脑配置无法使用
  5. 种树(codevs 1768)
  6. linux bash 逻辑,Bash 中的逻辑和() | Linux 中国
  7. java视频教程哪个好?
  8. 计算机辅助 高等数学教学,高等数学教学方法
  9. 日夕如是寒暑不间,基于Python3+Tornado6+APScheduler/Celery打造并发异步动态定时任务轮询服务
  10. 【linux3.10】内存反向映射中的anon_vma是per process的吗?
  11. Unity 游戏脚本
  12. js阿拉伯数字转中文汉字小写 支持到12位
  13. slxrom+v.21+原生android+4.2,小米MIX2S 魔趣OS 安卓9 MagiskV21版 完美ROOT 纯净完美 原生极简 纯净推荐...
  14. 将QuickDraw数据集ndjson转为png图片
  15. Charon的python数据可视化分析4(饼状图)
  16. 篮球队编程题(Java)
  17. VMware虚拟机网络详细设置(转载https://www.2cto.com/net/201103/85655.html)
  18. Windows Server 2012 蓝屏 Wpprecorder.sys 故障
  19. android校园通软件论文,基于Android平台的校园通掌上系统的设计与实现
  20. S波与P波的定义(光波电矢量)(菲涅耳公式)

热门文章

  1. 第21章 java线程(1)-线程初步
  2. Linux基础 权限与用户管理命令
  3. postifx网络服务的搭建和配置
  4. 一段MYSQL的插入代码
  5. JHipster简介
  6. 数据存储与访问之——初见SQLite数据库
  7. vue项目中moment的使用(时间戳格式化)
  8. 怀旧服最新开的服务器是哪个,魔兽世界怀旧服什么时候开服 魔兽世界怀旧服开服时间介绍...
  9. 增量式速度pid调节策略_增量式PID是什么?不知道你就落伍了
  10. java中的设计模式