当前位置:   article > 正文

go函数延迟调用defer_小袁今天刚学会了defer延迟调用

小袁今天刚学会了defer延迟调用

目录

一、defer执行顺序

二、延迟执行顺序

1、使用延迟并发解锁

2、使用延迟释放文件句柄


        在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行。不是defer的语句还是按照之前的执行顺序,顺序执行

一、defer执行顺序

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. fmt.Println("defer begin")
  7. // 将defer放入延迟调用栈
  8. defer fmt.Println(1)
  9. defer fmt.Println(2)
  10. // 最后一个放入, 位于栈顶, 最先调用
  11. defer fmt.Println(3)
  12. fmt.Println("defer end")
  13. }
  14. 代码输出如下:
  15. defer begin
  16. defer end
  17. 3
  18. 2
  19. 1

二、延迟执行顺序

defer 语句正好是在函数退出时执行的语句,所以使用 defer 能非常方便地处理资源释放问题。

1、使用延迟并发解锁

在下面的例子中会在函数中并发使用 map,为防止竞态问题,使用 sync.Mutex 进行加锁,参见下面代码:

  1. var (
  2. // 一个演示用的映射
  3. valueByKey = make(map[string]int)
  4. // 保证使用映射时的并发安全的互斥锁
  5. valueByKeyGuard sync.Mutex
  6. )
  7. // 根据键读取值
  8. func readValue(key string) int {
  9. // 对共享资源加锁
  10. valueByKeyGuard.Lock()
  11. // 取值
  12. v := valueByKey[key]
  13. // 对共享资源解锁
  14. valueByKeyGuard.Unlock()
  15. // 返回值
  16. return v
  17. }

使用 defer 语句对上面的语句进行简化,参考下面的代码。

  1. func readValue(key string) int {
  2. valueByKeyGuard.Lock()
  3. // defer后面的语句不会马上调用, 而是延迟到函数结束时调用
  4. defer valueByKeyGuard.Unlock()
  5. return valueByKey[key]
  6. }

2、使用延迟释放文件句柄

文件的操作需要经过打开文件、获取和操作文件资源、关闭资源几个过程,如果在操作完毕后不关闭文件资源,进程将一直无法释放文件资源。

  1. // 根据文件名查询其大小
  2. func fileSize(filename string) int64 {
  3. // 根据文件名打开文件, 返回文件句柄和错误
  4. f, err := os.Open(filename)
  5. // 如果打开时发生错误, 返回文件大小为0
  6. if err != nil {
  7. f.close()
  8. return 0
  9. }
  10. // 取文件状态信息
  11. info, err := f.Stat()
  12. // 如果获取信息时发生错误, 关闭文件并返回文件大小为0
  13. if err != nil {
  14. f.Close()
  15. return 0
  16. }
  17. // 取文件大小
  18. size := info.Size()
  19. // 关闭文件
  20. f.Close()
  21. // 返回文件大小
  22. return size
  23. }

在上面的例子中加粗部分是对文件的关闭操作。下面使用 defer 对代码进行简化,代码如下:

  1. func fileSize(filename string) int64 {
  2. f, err := os.Open(filename)
  3. if err != nil {
  4. return 0
  5. }
  6. // 延迟调用Close, 此时Close不会被调用
  7. defer f.Close()
  8. info, err := f.Stat()
  9. if err != nil {
  10. // defer机制触发, 调用Close关闭文件
  11. return 0
  12. }
  13. size := info.Size()
  14. // defer机制触发, 调用Close关闭文件
  15. return size
  16. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/675036
推荐阅读
相关标签
  

闽ICP备14008679号