Ezreal 书架 Ezreal 书架
Home
  • 《Go程序员面试笔试宝典》
  • 《RabbitMQ 实战指南》
  • 《深入理解kafka》
  • MySQL45讲
  • 透视HTTP协议
  • 结构化数据的分布式存储系统
  • Raft 共识算法
Home
  • 《Go程序员面试笔试宝典》
  • 《RabbitMQ 实战指南》
  • 《深入理解kafka》
  • MySQL45讲
  • 透视HTTP协议
  • 结构化数据的分布式存储系统
  • Raft 共识算法
  • 逃逸分析

  • 延迟语句

    • 延迟语句是什么
    • 延迟语句的执行顺序是什么
    • 如何拆解延迟语句
    • 如何确定延迟语句的参数
    • 闭包是什么
    • 延迟语句如何配合恢复语句
    • defer 链如何被遍历执行
    • 为什么无法从父 goroutine 恢复子 goroutine 的 panic
  • 数据容器

  • 通道

  • 接口

  • unsafe

  • context

  • Go程序员面试笔试宝典
  • 延迟语句
ezreal_rao
2023-04-23

延迟语句是什么

编程的时候,经常需要申请一些资源,比如数据库连接、文件、锁等,这些资源需要在用完之后释放掉,否则会造成内存泄漏。但编程人员经常容易忘记释放这些资源,从而造成一些事故。Go 语言直接在语言层面提供 defer 关键字,在申请资源语句的下一行,可以直接用 defer 语句来注册函数结束后执行释放资源的操作。因为这样一颗小小的语法糖,忘写关闭资源语句的情况就大大地减少了。

defer 是 Go 语言提供的一种用于注册延迟调用的机制:让函数或语句可以在当前函数执行完毕后(包括通过 return 正常结束或者 panic 导致的异常结束)执行。在需要释放资源的场景非常有用,可以很方便地在函数结束前做一些清理操作。在打开资源语句的下一行,直接使用 defer 就可以在函数返回前释放资源,可谓相当有效。

defer 通常用于一些成对操作的场景:打开连接 / 关闭连接、加锁 / 释放锁、打开文件 / 关闭文件等。使用非常简单:

f,err := os.Open(filename)
if err != nil {
    panic(err)
}
if f != nil {
    defer f.Close()
}
1
2
3
4
5
6
7

在打开文件的语句附近,用 defer 语句关闭文件。这样,在函数结束之前,会自动执行 defer 后面的语句来关闭文件。注意,要先判断 f 是否为空,如果 f 不为空,再调用 f.Close () 函数,避免出现异常情况。

当然,defer 会有短暂延迟,对时间要求特别高的程序,可以避免使用它,其他情况一般可以忽略它带来的延迟。特别是 Go 1.14 又对 defer 做了很大幅度的优化,效率提升了不少。

我们以一个反面例子来结束这一节:

r.mu.Lock()
rand.Intn(param)
r.mu.Unlock()
1
2
3

上面只有三行代码,看起来这里不用 defer 执行 Unlock 并没有什么问题。其实并不是这样, 中间这行代码 rand.Intn (param) 其实是有可能发生 panic 的,更严重的情况是,这段代码很有可能被其他人修改,增加更多的逻辑,而这完全不可控。也就是说,在 Lock 和 Unlock 之间的代码一旦出现异常情况导致 panic,就会形成死锁。因此这里的逻辑是,即使是看起来非常简单的代码,使用 defer 也是有必要的,因为需求总是在变化,代码也总会被修改。

#延迟语句#defer
上次更新: 5/9/2023, 10:58:32 AM
Go与其他语言的堆和栈是同一个概念吗
延迟语句的执行顺序是什么

← Go与其他语言的堆和栈是同一个概念吗 延迟语句的执行顺序是什么→

最近更新
01
为什么我的MySQL会抖一下
07-15
02
HTTP 性能优化面面观
07-12
03
WebSocket:沙盒里的 TCP
07-12
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Ezreal Rao | CC BY-NC-SA 4.0
豫ICP备2023001810号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式