Go defer函数 延迟执行
2023-09-14 09:15:18 时间
defer
func TestDefer(t *testing.T) {
defer func() { //后面可以是命名函数,或者匿名函数,总之是函数调用
t.Log("Clear resources")
}()
t.Log("Started")
panic("Fatal error”) //defer仍会执⾏,如果是其他语句放在Panic之后,那么这行语句是不可达的,也就是Panic后面的语句是不可执行的
}
defer的函数调用不会立刻执行,而是会执行Panic语句,执行完了在函数返回前才会执行defer的函数,
依据这种特性,可能会想到在java里面的try finally的结构,这个类似于finally,最后返回时候执行的。
这有什么用呢,通常都是清理某些资源,释放某些锁,不管是报了异常还是异常退出了,都不会忘记将我们的锁/资源释放掉,以免导致资源的浪费,导致程序被锁住。
这里抛出了Panic,这里是程序异常中断,在go里面代表不可修复的错误。即便是在Panic的情况下,defer后面的函数也是会执行的。
defer 关键字用户声明函数,
不论函数是否发生错误都在函数执行最后执行(return 之前)
,
若使用 defer 声明多个函数,则按照声明的顺序,先声明后执行(堆) 常用来做资源释放
,记录日志等工作。
defer后面一般是加匿名函数的调用
fmt.Println("start")
defer func() {
fmt.Println("defer")
}()
fmt.Println("end")
start
end
defer
defer的作用就是延时执行,defer延时到什么时候呢,延时到函数退出之前执行。
mt.Println("start")
defer func() {
fmt.Println("defer1")
}()
defer func() {
fmt.Println("defer2")
}()
fmt.Println("end")
start
end
defer2
defer1
可以看到是堆栈的模式,谁先声明,最后执行。
Deferred 函数
在一个自定义函数中,你打开了一个文件,然后需要关闭它以释放资源。不管你的代码执行了多少分支,是否出现了错误,文件是一定要关闭的,这样才能保证资源的释放。
如果这个事情由开发人员来做,随着业务逻辑的复杂会变得非常麻烦,而且还有可能会忘记关闭。基于这种情况,Go 语言为我们提供了 defer 函数,可以保证文件关闭后一定会被执行,不管你自定义的函数出现异常还是错误。
延时执行有个关键字defer,defer后面跟着的是函数调用,函数调用就是要加括号的。
下面的代码是 Go 语言标准包 ioutil 中的 ReadFile 函数,它需要打开一个文件,然后通过 defer 关键字确保在 ReadFile 函数执行结束后,f.Close() 方法被执行,这样文件的资源才一定会释放。
func ReadFile(filename string) ([]byte, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
//省略无关代码
return readAll(f, n)
}
defer 关键字用于修饰一个函数或者方法,使得该函数或者方法在返回前才会执行,也就说被延迟,但又可以保证一定会执行。
以上面的 ReadFile 函数为例,被 defer 修饰的 f.Close 方法延迟执行,也就是说会先执行 readAll(f, n),然后在整个 ReadFile 函数 return 之前执行 f.Close 方法。
defer 语句常被用于成对的操作,如文件的打开和关闭,加锁和释放锁,连接的建立和断开等。不管多么复杂的操作,都可以保证资源被正确地释放。
相关文章
- 延宕执行,妙用无穷,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中defer关键字延迟调用机制使用EP17
- 你有对象类,我有结构体,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang结构体(struct)的使用EP06
- Go 面向对象编程篇(三):通过组合实现类的继承和方法重写
- 2020 GO vs Python 应该选择哪一个
- 理解真实项目中的 Go 并发 Bug
- Go常见错误集锦之map
- 「Go工具箱」一个对语义化版本进行解析、比较的库:go-version
- 2023-02-22:请用go语言调用ffmpeg,保存mp4文件的视频帧,每帧用ppm图片保存。
- 天呐!我用 go 从零开始写了一个 k8s 应用管理工具(附完整代码和开发过程)
- Go-包管理-go get(一)
- Go-包管理-go get(二)
- Go语言变量的作用域
- Go语言通过反射获取结构体的成员类型
- Linux下安装Go环境指南(linux安装go环境)
- Go语言环境配置:在 Linux 下实现(go环境搭建linux)
- SQL Server和Go组合,助力数据库计算更高效(sqlserver加go)
- 提升Go读取Oracle的速度(go读取oracle速度)