概述
对于资源释放,有很多不同的实现方式,不同语言也有不同的惯用方法。
  • C语言 :手动管理
  • Golang :defer
  • Python :上下文管理器contexManager
  • C++ : 作用域和析构函数
  • Rust :所有权和drop trait
如果了解上面几种语言的童鞋应该知道,
C语言资源管理是比较麻烦的,一旦资源使用过程中出错,就可能造成资源泄漏。
Golang通过defer,即使过程中panic,也可以释放资源。
Python通过上下文管理器,主要是两个magic function`__enter__`, `__exit__`来保证资源的释放。
C++和Rust相似,都是在某种语义下自动调用释放函数。但是Rust有所有权检查,可以防止写代码犯傻 (比如C++不小心拷贝了一下。)
 
 
以上来看,C++和Rust的必须要在编程时注意释放的时机,也就是需要程序员更多的思考。但是Rust编译器会帮你一下,而C++并不会。
其次Python和Golang都使用了显式管理,一定不能忘了做,不过做了问题就不大了。
 
defer
不过这是一篇关于derfer的文章,写一下defer需要注意的重点(就是读Effective Go的一点笔记)。
 
基本使用
`defer语句将函数调用安排在当前函数结束前执行。也就是defer 语句中的函数调用是当前函数最后执行的东西`
- 一个经典的例子
 // Contents returns the file's contents as a string.
 func Contents(filename string) (string, error) {
     f, err := os.Open(filename)
     if err != nil {
         return "", err
     }
     defer f.Close()  // f.Close will run when we're finished.

     var result []byte
     buf := make([])
     for {
         n, err := f.Read(buf[:])
         result = append(result, buf[:n]...) // append is discussed later.
         if err != nil {
             if err == io.EOF {
                 break
             }
             return "", err  // f will be closed if we return here.
         }
     }
     return string(result), nil // f will be closed if we return here.
 }
 
用上面的话翻译代码中的`defer f.Close()`就是“将f.Close()放在Contents函数的最后执行”
将`f.Close()`放在defer后面有两个好处:保证资源释放、离`Open`比较近不会忘了做。
这没什么好说的,golang必须显式释放资源。
 
细节
首先明确两个概念
- defer语句执行
    将defer语句中函数调用安排在了当前函数结束前执行
- 函数调用执行
    运行defer语句中的函数调用
 
参数求值
这里的参数求值指的是defer语句中函数调用的参数。
参数在defer语句执行求值,而不是在函数调用执行时求值。
- 又一个例子
func trace(s string) string {
    fmt.Println("entering:", s)
    return s
}

func un(s string) {
    fmt.Println("leaving:", s)
}

func a() {
    defer un(trace("a"))
    fmt.Println("in a")
}

func b() {
    defer un(trace("b"))
    fmt.Println("in b")
    a()
}

func main() {
    b()
}
首先看函数b,因为参数是在defer语句执行时求值的,所以`trace("b")`要先被求值[先打印"b",再返回"b"],然后再往下执行,在函数b结束之前会调用`un("b")`.
同理如函数a。现在猜一下执行结果。
 
entering: b
in b
entering: a
in a
leaving: a
leaving: b
 
执行顺序
当有多个defer语句的时候,到底是谁的函数调用先执行呢?
 
 ; i < ; i++ {
     defer fmt.Printf("%d ", i)
 }

defer的函数调用按着后进先出(LIFO)的方式执行。大概猜一猜,每次defer都会将函数调用压入栈中,最后依次出栈执行。

 
最后
golang中defer也就主要用在资源管理上了。明确以上几点问题,应该问题不大了(吹牛ing)。
 
 

golang之defer的更多相关文章

  1. 关于golang的defer的练习

    golang的defer怎么说.大意就是在函数return后.函数关闭前.按照filo的顺序来执行的关键字 上代码: package main import ( "fmt" ) f ...

  2. golang学习 ---defer语句

    golang语言defer特性详解 defer语句是go语言提供的一种用于注册延迟调用的机制,它可以让函数在当前函数执行完毕后执行,是go语言中一种很有用的特性.由于它使用起来简单又方便,所以深得go ...

  3. 延宕执行,妙用无穷,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中defer关键字延迟调用机制使用EP17

    先行定义,延后执行.不得不佩服Go lang设计者天才的设计,事实上,defer关键字就相当于Python中的try{ ...}except{ ...}finally{...}结构设计中的finall ...

  4. golang中defer的使用规则

    转自个人博客chinazt.cc 在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函数正常返回,也就是return之后添加一个函数调用. ...

  5. [转]golang中defer的使用规则

    转载于:https://studygolang.com/articles/10167 在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函 ...

  6. golang中defer的理解

    在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函数正常返回,也就是return之后添加一个函数调用.因此,defer通常用来释放函数内 ...

  7. 【GoLang】golang 中 defer 参数的蹊跷

    参考资料: http://studygolang.com/articles/7994--Defer函数调用参数的求值 golang的闭包和普通函数调用区别:http://studygolang.com ...

  8. golang 之 defer(统计函数执行时间)

    package main import ( "fmt" "time" ) func sum(a ...int) int { defer trace(" ...

  9. golang中defer的详解 转自https://blog.csdn.net/skh2015java/article/details/77081250

    Go里的defer很有用,尤其在很多执行模块化操作时,初始化时给各个需要执行的模块传入参数,但是这些参数有些事在模块执行过程中才赋值的. 这时候有了defer就不会把代码写的很凌乱. Go的defer ...

随机推荐

  1. Kafka的基本概念

    Kafka的前身是由LinkedIn开源的一款产品,2011年初开始开源,加入了 Apache 基金会,2012年从 Apache Incubator 毕业变成了 Apache 顶级开源项目. Top ...

  2. 洛谷P2038 无线网络发射器选址

    题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的 \(129\) 条东西向街道和 \(129\) 条南北向街道所形 ...

  3. 【题解】洛谷 P1449 后缀表达式

    目录 题目 思路 \(Code\) 题目 P1449 后缀表达式 思路 栈.题目说的不是很清楚,没说包含什么操作.除法用整数除法就行. 先string读入字符串,然后从前往后看如果是个数字就入栈,如果 ...

  4. 洛谷1169 [ZJOI2007] 棋盘制作

    题目链接 题意概述:给出由0 1构成的矩阵,求没有0 1 相邻的最大子矩阵的最大子正方形. 解题思路:设f[i][j]表示i j向上能到哪,l[i][j] r[i][j]表示向左/右,转移时分开计算矩 ...

  5. 多catch块的代码优化

    一.多catch块的代码优化 在写代码时,多行存在不同的异常,使用try catch的话,习惯性的是有多个catch,如下所示: 注意到warning,文字描述如下: Reports identica ...

  6. Android Studio 之 DataBing ,不需要再一个个findViewById了

    使用DataBinding,不需要再一个个findViewById了 1.在 build.gradel 中 添加下面语句 dataBinding{ enabled true } 2.在 activit ...

  7. Linux 删除文件未释放空间问题处理,下清空或删除大文件

    linux里的文件被删除后,空间没有被释放是因为在Linux系统中,通过rm或者文件管理器删除文件将会从文件系统的目录结构上解除链接(unlink).然而如果文件是被打开的(有一个进程正在使用),那么 ...

  8. visual studio 2019 企业版下载

    由于visual studio从2017开始就是网络下载安装,所以网速慢的朋友安装上就存在时间感,所以笔者在百度云上提供了visual studio 2019的下载包.需要的朋友自己下载安装.不过,2 ...

  9. 微信小程序 调用远程接口,给全局数组赋值

    关键是 let that = this 因为在onLoad 的 wx.request方法里, this指的是 wx.request 的上下文, 所以应该是在 onLoad 的时候定义 let that ...

  10. pandas连接多个表格concat()函数

    网易云课堂该课程链接地址 https://study.163.com/course/courseMain.htm?share=2&shareId=400000000398149&cou ...