Go语言之Defer篇(三)

欢迎关注公众号:灰子学技术

写在前面的话:

在接触defer之后,觉得Go的这一特性很好,有点类似于C++的析构函数,不过他们却有很大的不同。主要的区别点是defer实现在函数里面,作用域也是在函数里面,当函数的return语句被调用之后,才会调用到这个defer声明的函数。而析构函数实现在类里面,作用域是在类内部,在该类的实例被销毁的时候,就会被调用到。

在谈论defer之前,笔者问了自己三个问题:
为什么我们需要defer?
如何才能更好的使用它?
defer是如何实现的?

基于上面的三个问题,笔者做了简单的整理。

一.为什么我们需要defer

我们在写程序的时候,往往会碰到下面的两种情况。

第一种释放资源,当我们在创建一个资源的时候,往往需要释放资源,但是因为逻辑分支太多的缘故,我们要在每一个异常分支里面去实现释放资源的 操作。这样以来的话,就存在两个问题,第一,我们需要散弹式修改,释放资源的地方很多,每个都要填写上面,代码不容易维护。第二,异常分支太多的话,很容易漏掉,或者提前return了,进而导致资源没有释放掉,这样会产生代码漏洞。

第二种处理异常,代码实现里面,有一些异常是可以从逻辑代码里面控制的,有一些却未必容易控制,特别是一些很难捕捉到到异常,这种主要来源于操作系统内核或者硬件提示的异常信息。

1.C++里面这两种情况,都有对应的处理方法,第一种采用析构函数去释放这些资源,第二种情况采用try-catch的方式去捕获和处理这些异常(备注:这部分内容会专门整理一篇文章介绍)。

2.到了Go之后,我发现C++的这两种实现方式都不存在了,那怎么办呢?于是defer产生了,这种在普通函数的return之后会调用的延迟调用函数,该发挥作用了。

二.defer的使用规则

defer函数调用时间,发生在该函数的return之后,主要用三种使用规则,说是三种规则,其实更像是三种注意事项。

1)当defer被声明时,其参数就会被实时解析。

package main
import (
"fmt"
)
func main() {
var i int = 1
// i的值在defer第一次走到的位置就被确认下来了
defer fmt.Println("defer i value:", i)
i++
fmt.Println("Main i value:", i)
}

output:

Main i value: 2
defer i value: 1

备注:对于指针来说,这个参数是地址,指针指向的数据还是有可能会被更改的。

2)当一个函数中有多个defer函数时,它们的执行顺序是先进后出。

这种处理场景,一般是有几个资源,而这些资源之间是有依赖关系的。

剩余内容还请访问:Go语言之defer

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、数据类型转换 https://studygolang.com/articles/10838 package m...
    蓓蓓的万能男友阅读 1,161评论 0 1
  • Golang是我最喜欢的一门语言,它简洁、高效、易学习、开发效率高、还可以编译成机器码… 虽然它一出世,就饱受关注...
    盘木阅读 3,695评论 0 7
  • fmt格式化字符串 格式:%[旗标][宽度][.精度][arg索引]动词旗标有以下几种:+: 对于数值类型总是输出...
    皮皮v阅读 1,220评论 0 3
  • 使用定时器t := time.NewTicker(1 * time.Second)// 第一种方式for { ...
    qishuai阅读 1,008评论 0 2
  • 函数 Go语言函数格式func 函数名称(形参列表)(返回值列表){函数语句} Go语言函数的类型没有返回值没有形...
    喝酸奶要舔盖__阅读 438评论 0 0

友情链接更多精彩内容