Go实战--golang中defer的使用
原址
生命不止,继续 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
5
1
要使用defer时不踩坑,最重要的一点就是要明白,return xxx这一条语句并不是一条原子指令!
函数返回的过程是这样的:先给返回值赋值,然后调用defer表达式,最后才是返回到调用函数中。
defer表达式可能会在设置函数返回值之后,在返回到调用函数之前,修改返回值,使最终的函数返回值与你想象的不一致。
出自:https://tiancaiamao.gitbooks.io/go-internals/content/zh/03.4.html
Go实战--golang中defer的使用相关推荐
- Go实战--golang中使用echo框架中JSONP(labstack/echo)
生命不止,继续 go go go !!! 继续,echo web框架,今天就聊一聊JSONP. JSONP 1.什么是JSONP? JSONP (JSON with padding) is used ...
- Go实战--golang中OAuth2.0的使用(使用google账号进行登陆验证)
生命不止,继续 go go go!!! 今天继续分享golang中的认证问题,之前写过两篇: 一篇是关于basic认证:Go实战–通过basic认证的http(basic authentication ...
- Go实战--golang中操作PDF(rsc.io/pdf、jung-kurt/gofpdf、signintech/gopdf)
生命不止,继续 go go go !!! 昨天介绍了golang中如何操作excel: Go实战–golang中操作excel(tealeg/xlsx.360EntSecGroup-Skylar/ex ...
- 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 ...
- Go实战--golang中使用redis(redigo和go-redis/redis这个已测试)
自己做测试了没有问题,虚拟机连不上可以把包下载到本地. 版权声明:本文为博主原创文章,未经博主允许不得转载. http://blog.csdn.net/wangshubo1989/article/de ...
- Go实战--golang中使用JWT(JSON Web Token)
生命不止,继续 go go go !!! 之前写过关于golang中如何使用cookie的博客: 实战–go中使用cookie 今天就来跟大家简单介绍一下golang中如何使用token,当然是要依赖 ...
- Go实战--golang中使用gRPC和Protobuf实现高性能api(golang/protobuf、google.golang.org/grpc)
生命不止,继续 go go go !!! 号外号外,插播一条广告,通过博客的uv可以看到周五,程序员是不怎么干活的: 本篇博客,使用gRPC和Protobuf,实现所谓的高性能api. protobu ...
- Go实战--golang中使用号称全世界最快的JSON解析器json-iterator(json-iterator/go)
生命不止,继续go go go!!! 号外号外,差不一条广告,我的博客六月到十一月UV的地域分布: golang中的使用json一点也不陌生,golang为我们提供了官方的encoding/json: ...
- Go实战--golang中使用redis(redigo和go-redis/redis)
生命不止,继续 go go go !!! 以前介绍过golang中如何使用sqlite3: <Go实战–go语言操作sqlite数据库(The way to go)> 今天跟大家分享的是如 ...
最新文章
- 这是时间的推移 不是系统的分类
- 内存不足 java.lang.OutOfMemoryError: Java heap space
- 发现还是 True Image Server v8.1.941 比较好用
- win8 打开计算机配置,win8.1 更改电脑配置无法使用
- 种树(codevs 1768)
- linux bash 逻辑,Bash 中的逻辑和() | Linux 中国
- java视频教程哪个好?
- 计算机辅助 高等数学教学,高等数学教学方法
- 日夕如是寒暑不间,基于Python3+Tornado6+APScheduler/Celery打造并发异步动态定时任务轮询服务
- 【linux3.10】内存反向映射中的anon_vma是per process的吗?
- Unity 游戏脚本
- js阿拉伯数字转中文汉字小写 支持到12位
- slxrom+v.21+原生android+4.2,小米MIX2S 魔趣OS 安卓9 MagiskV21版 完美ROOT 纯净完美 原生极简 纯净推荐...
- 将QuickDraw数据集ndjson转为png图片
- Charon的python数据可视化分析4(饼状图)
- 篮球队编程题(Java)
- VMware虚拟机网络详细设置(转载https://www.2cto.com/net/201103/85655.html)
- Windows Server 2012 蓝屏 Wpprecorder.sys 故障
- android校园通软件论文,基于Android平台的校园通掌上系统的设计与实现
- S波与P波的定义(光波电矢量)(菲涅耳公式)