go语言defer使用 .
来源:互联网 发布:网络编程socket 编辑:程序博客网 时间:2024/05/17 07:42
defer
Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题。如下代码所示,我们一般写打开一个资源是这样操作的:
我们看到上面有很多重复的代码,Go的defer
有效解决了这个问题。使用它后,不但代码量减少了很多,而且程序变得更优雅。在defer
后指定的函数会在函数退出前调用。
如果有很多调用defer
,那么defer
是采用后进先出模式,所以如下代码会输出4 3 2 1 0
defer 给我的第一印象就是,类似java中的
try {
}finally {
}
我目前的理解就是,在函数块中使用defer,就是函数对应的有一个栈空间,先进后出。需要函数结束后调用栈,来出发defer操作。
如果,一个对象的创建,很消耗内存,需要及时关闭,defer无法像try finnaly哪样准确。
- package main
- import "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]$
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 main
- import "fmt"
- import "time"
- type User struct {
- username string
- }
- func (this *User) Close() {
- fmt.Println(this.username, "Closed !!!")
- }
- func main() {
- {
- // 即便加了代码快范围,依旧也要主函数体结束才执行defer
- u1 := &User{"jack"}
- defer u1.Close()
- }
- u2 := &User{"lily"}
- defer u2.Close()
- time.Sleep(10 * time.Second)
- fmt.Println("Done !")
- }
package mainimport "fmt"import "time"type User struct { username string}func (this *User) Close() { fmt.Println(this.username, "Closed !!!")}func main() { { // 即便加了代码快范围,依旧也要主函数体结束才执行defer u1 := &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 main
- import "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()<PRE class=plain name="code"> func() {
- defer u2.Close()
- // u2 do somthing
- }()</PRE> time.Sleep(10 * time.Second) fmt.Println("Done !")}func f(u *User) { defer u.Close() // u1 do gomething}
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()<div class="dp-highlighter bg_plain"><div class="bar"><div class="tools"><strong>[plain]</strong> <a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/eclipser1987/article/details/12089271#">view plain</a><a target=_blank class="CopyToClipboard" title="copy" href="http://blog.csdn.net/eclipser1987/article/details/12089271#">copy</a><a target=_blank class="PrintSource" title="print" href="http://blog.csdn.net/eclipser1987/article/details/12089271#">print</a><a target=_blank class="About" title="?" href="http://blog.csdn.net/eclipser1987/article/details/12089271#">?</a><a target=_blank href="http://blog.csdn.net/eclipser1987/article/details/12089271"></a></div></div><ol><li class="alt"><span><span>func() { </span></span></li><li><span> defer u2.Close() </span></li><li class="alt"><span> // u2 do somthing </span></li><li><span>}() </span></li></ol></div><pre style="DISPLAY: none" class="plain" name="code"> 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使用
- go语言defer使用
- go语言defer使用 .
- Go语言defer的使用
- go语言, defer con.Close() 使用之一
- Go语言之defer
- Go语言defer
- go语言-defer关键字
- 52.笔记go语言——defer使用场景
- go语言 golang defer 关注点
- go语言defer的用法
- Go语言中的defer关键字
- Go语言defer学习小结
- GO语言defer延迟代码
- 关于Go语言中defer关键字
- Go语言优雅设计之-defer(延迟)
- go语言defer执行时机简单分析
- GO语言延迟函数defer用法分析
- TexturePacker
- Velocity宏定义的坑与解决办法
- 游戏中的脚本语言原理与发展
- Minimum Path Sum
- Tiny Formater
- go语言defer使用 .
- ListView setSelection 无效问题
- http://blog.csdn.net/lenotang/article/details/2823230
- JSON详解
- Leetcode[66]-Plus One
- Tiny之Web工程构建
- 开源框架Tiny之内容组成
- 第一章,listview的简易用法(Android)
- TinyUI组件开发示例