码迷,mamicode.com
首页 > 其他好文 > 详细

golang中defer的些许总结

时间:2020-07-12 18:26:31      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:put   顺序   特性   数据   变量   com   ==   nil   忘记   

引言

最近自己在学习go项目的时候,查看别人的源码经常发现defer的使用,加上自己之前对这个关键字没怎么在意,只知道差不多是用来释放内部变量的。

查看资料可以发现,defer会在当前函数或者方法返回之前执行传入的函数,经常用于关闭文件描述符、关闭数据库连接以及解锁资源

为了能够更形象地理解defer的行为,我就在这贴上一段关闭文件描述符的示例代码:

func?CopyFile(source,?dest?string)?bool?{
????if?source?==?""?||?dest?==?""?{
????????log.Println("source?or?dest?is?null")
????????return?false
????}
????source_open,?err?:=?os.Open(source)
????if?err?!=?nil?{
????????log.Println(err.Error())
????????return?false
????}
????defer?source_open.Close()
????dest_open,?err?:=?os.OpenFile(dest,?os.O_CREATE|os.O_WRONLY,?644)
????if?err?!=?nil?{
????????log.Println(err.Error())
????????return?false
????}
????defer?dest_open.Close()
????_,?copy_err?:=?io.Copy(dest_open,?source_open)
????if?copy_err?!=?nil?{
????????log.Println(copy_err.Error())
????????return?false
????}?else?{
????????return?true
????}
}

在示例代码中,使用了defer来关闭文件流,用来避免忘记文件释放的问题。

defer的调用时机以及多次调用defer的执行顺序

defer传入的函数会在当前调用方法返回之前得到运行。

为了更好地解释上面的原理,通过一个简单例子来观察就很明显了:

func?main()?{
????for?i?:=?0;?i?<?4;?i++?{
????????defer?fmt.Println(i)
????}???
}

示例程序中是用来循环输出数字的,实际上的运行结果如下,可以观察得出defer的效果类似于栈的先进后出:

3 
2 
1 
0

defer的预计算参数

defer继承了Go中函数调用的特性,就是函数调用都是传值的。所以,使用defer关键字之后,会立刻对函数中引用的外部参数进行拷贝

示例程序如下,最后包含了输出结果:

func?PrintInfo()?{
????val?:=?0
????fmt.Println("use?defer?to?print?val-->")
????//?in?here,?will?output?0
????defer?fmt.Println(val)
????val++
????//?in?here,?will?output?1
????defer?fmt.Println(val)
????return
}

use defer to print val--> 
1 
0

至于程序为什么会输出1 0 而不是 0 1 ,答案已经在上面有了解释;

参考资料

golang中defer的些许总结

标签:put   顺序   特性   数据   变量   com   ==   nil   忘记   

原文地址:https://www.cnblogs.com/zuixime0515/p/13289087.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!