- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章golang中defer的关键特性示例详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
大家都知道golang的defer关键字,它可以在函数返回前执行一些操作,最常用的就是打开一个资源(例如一个文件、数据库连接等)时就用defer延迟关闭改资源,以免引起内存泄漏。本文主要给大家介绍了关于golang中defer的关键特性,分享出来供大家参考学习,下面话不多说,来一起看看详细的介绍:
1、defer 的作用和执行时机 。
go 的 defer 语句是用来延迟执行函数的,而且延迟发生在调用函数 return 之后,比如 。
1
2
3
4
|
func a() int {
defer b()
return 0
}
|
b 的执行是发生在 return 0 之后,注意 defer 的语法,关键字 defer 之后是函数的调用.
2、defer 的重要用途一:清理释放资源 。
由于 defer 的延迟特性,defer 常用在函数调用结束之后清理相关的资源,比如 。
1
2
|
f, _ := os.Open(filename)
defer f.Close()
|
文件资源的释放会在函数调用结束之后借助 defer 自动执行,不需要时刻记住哪里的资源需要释放,打开和释放必须相对应.
用一个例子深刻诠释一下 defer 带来的便利和简洁.
代码的主要目的是打开一个文件,然后复制内容到另一个新的文件中,没有 defer 时这样写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
dst, err := os.Create(dstName)
if err != nil { //1
return
}
written, err = io.Copy(dst, src)
dst.Close()
src.Close()
return
}
|
代码在 #1 处返回之后,src 文件没有执行关闭操作,可能会导致资源不能正确释放,改用 defer 实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close()
dst, err := os.Create(dstName)
if err != nil {
return
}
defer dst.Close()
return io.Copy(dst, src)
}
|
src 和 dst 都能及时清理和释放,无论 return 在什么地方执行.
鉴于 defer 的这种作用,defer 常用来释放数据库连接,文件打开句柄等释放资源的操作.
3、defer 的重要用途二:执行 recover 。
被 defer 的函数在 return 之后执行,这个时机点正好可以捕获函数抛出的 panic,因而 defer 的另一个重要用途就是执行 recover.
recover 只有在 defer 中使用才更有意义,如果在其他地方使用,由于 program 已经调用结束而提前返回而无法有效捕捉错误.
1
2
3
4
5
6
7
8
9
10
11
12
|
package main
import (
"fmt"
)
func main() {
defer func() {
if ok := recover(); ok != nil {
fmt.Println("recover")
}
}()
panic("error")
}
|
记住 defer 要放在 panic 执行之前.
4、多个 defer 的执行顺序 。
defer 的作用就是把关键字之后的函数执行压入一个栈中延迟执行,多个 defer 的执行顺序是后进先出 LIFO :
1
2
3
|
defer func() { fmt.Println("1") }()
defer func() { fmt.Println("2") }()
defer func() { fmt.Println("3") }()
|
输出顺序是 321.
这个特性可以对一个 array 实现逆序操作.
5、被 deferred 函数的参数在 defer 时确定 。
这是 defer 的特点,一个函数被 defer 时,它的参数在 defer 时进行计算确定,即使 defer 之后参数发生修改,对已经 defer 的函数没有影响,什么意思?看例子:
1
2
3
4
5
6
|
func a() {
i := 0
defer fmt.Println(i)
i++
return
}
|
a 执行输出的是 0 而不是 1,因为 defer 时,i 的值是 0,此时被 defer 的函数参数已经进行执行计算并确定了.
再看一个例子:
1
2
3
4
5
6
7
8
9
10
11
12
|
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
a := 1
b := 2
defer calc("1", a, calc("10", a, b))
a = 0
return
}
|
执行代码输出 。
1
2
|
10 1 2 3
1 1 3 4
|
defer 函数的参数 第三个参数在 defer 时就已经计算完成并确定,第二个参数 a 也是如此,无论之后 a 变量是否修改都不影响.
6、被 defer 的函数可以读取和修改带名称的返回值 。
1
2
3
4
|
func c() (i int) {
defer func() { i++ }()
return 1
}
|
被 defer 的函数是在 return 之后执行,可以修改带名称的返回值,上面的函数 c 返回的是 2.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我的支持.
参考资料 。
https://blog.golang.org/defer-panic-and-recover 。
原文链接:http://sanyuesha.com/2017/07/23/go-defer/ 。
最后此篇关于golang中defer的关键特性示例详解的文章就讲到这里了,如果你想了解更多关于golang中defer的关键特性示例详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在 javascript 中使用 defer 属性的正确语法是什么? 我见过有两种方式: 1: ... 2: ... 根据经验 [和我找不到的引用资料],我更倾向于使用第二个选项,但我只是仔细检查了
有什么区别 var dfd = new $.Deferred 和 var dfd = $.Deferred 在哪些情况下需要使用 new 与不使用它? 最佳答案 jQuery official doc
给定使用 Promise 构造函数的代码 let promise = () => new Promise(resolve => resolve(1)); new Promise((resolve, r
我正在研究 RxKotlin,问题出现了:defer() 和 defer{} 有什么区别 最佳答案 defer() 和 defer {} 只是写同一件事的两种方式。 Kotlin 在某些特定情况下允许
我正在尝试使用 Python 在 Google App Engine 上执行此操作: def add_to_db(person): a = PersonDb(key_name = perso
所以我有一个延迟对象数组dataCalls。 目前我正在使用以下方法来解雇所有这些,并在所有 Deferreds 解决后调用回调: $.when.apply(null, dataCalls) .
考虑以下几点: function foo(){ // Returns the jQuery deffered below. var urlToUse; $.ajax({
我刚刚看到此代码已被弃用,我一直在尝试遵循此指南:http://www.codelord.net/2015/09/24/$q-dot-defer-youre-doing-it-wrong/以正确的方式
我有一些元素,其中一些代码依赖于其他 中的代码元素。我看到了defer属性在这里可以派上用场,因为它允许推迟执行代码块。 为了测试它,我在 Chrome 上执行了这个:http://jsfiddle
我需要向 jQuery 的 .when() 监视的函数添加未知数量(仅在运行时已知)的 .pipe() 调用。这些调用将基于另一个异步操作的 ajax 调用。请参阅下面的代码以获得更清晰的解释: $.
我正在使用 GAE 的“deffered” ' 库 (python),它会在出现异常时自动重试任务。 有没有办法知道(在任务处理函数中)任务已尝试的次数? 我的最终目标是实现如下内容: if num_
我有几个 元素,其中一些代码依赖于其他 中的代码元素。我看到了defer属性在这里可以派上用场,因为它允许代码块在执行中被推迟。 为了测试它,我在 Chrome 上执行了这个:http://jsfi
在我看来,两者都做同样的事情。 文档: deferred.always() deferred.then() 最佳答案 看起来deferred.then()允许您传递两个单独的成功和失败回调,而 def
我正在使用 Twisted 编写代码,但在为我的扭曲互联网延迟变量想出一个合理的变量名时遇到了麻烦。这是我的候选人: d :太通用,太短,违反了 pylint 规则 C0103。 def :与内置函数
是否存在这样的情况:调用 .callback() 或 .errback() 会向调用者引发异常,而该异常不会被延迟捕获? 假设我有以下延迟和回调: from twisted.internet impo
这是代码: http://jsbin.com/lizami/edit?js,console 将代码也粘贴到此处: var aaa = $.Deferred(); var bbb = function(
这是我的尝试: deferred.defer(class1().method1, class2.method2, arg) deferred.defer(class1().method1, class
我正在尝试使用 google.appengine.ext.deferred 来运行任务。我正在将一个方法传递给 defer() 方法,该方法成功运行,但在返回时抛出一个 ValueError: F
这个问题在这里已经有了答案: What's the difference between a Deferred object and its own promise object? (3 个答案)
我下载了一个名为 jsdeferred 的库来尝试帮助我解决一些代码流问题,但我有点迷茫,因为它的示例和...“文档” 在某些事情上有点不清楚。但是当我继续阅读和挖掘,当然还有谷歌搜索阳光下的一切时,
我是一名优秀的程序员,十分优秀!