16.defer 让代码更清晰

.container .card .information strong · · 348 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

本文视频地址

一 defer是什么

日常我们写如下的代码

var mu sync.Mutex
mu.Lock()
count++
mu.Unlock()

这样的代码特点就是在函数中会申请一些资源并在函数退出前释放或关闭资源。函数的实现需要资源在函数退出时被及时地释放,无论函数的执行时按预期进行,还是抛错。为此,程序员需要对函数中的错误里特别关注,在错误处理时不能忘记释放资源。这样让程序员需要思考的问题就会增加。同时多个资源释放怎么办?多个资源抛错怎么办?这样的逻辑将变得十分复杂,代码可读性也会极大降低,那程序的健壮性也是无法保证的。

我们看看Go语言中的defer如何解决上面的问题。

defer

1 只有在函数(方法)内部才能使用。
2 defer + 函数(方法),这些函数被称为deferred函数。defer将注册到其所在goroutine用于存放deferred函数的栈数据结构中,这些deferred函数将在执行defer的函数退出前被按后进先出(LIFO)的顺序调度执行。无论是执行到函数尾部返回,还是在某个粗偶处理分支显示renturn,还是panic,已经存储到deferred函数栈中的函数都会被调度执行。因此,deferred函数是一个可以在任何情况下都可以为函数进行收尾工作。

var mu sync.Mutex
mu.Lock()
defer mu.Unlock()
count++

上面的例子,我们用defer改写一下,只要Lock方法被调用,就使用defer + Unlock方法让锁和解锁成对出现,逻辑简化更加清晰。

二 defer 的常见用法

下面我们通过deferred函数拦截panic并恢复了程序,继续运行:

func MakePanic(){
    fmt.Println("制造一个panic")
    panic("111")
}

func Survive() {
    defer func() {
        if e:=recover();e!=nil{
            fmt.Println(e)
            fmt.Println("我来拯救你这个panic")
        }
    }()
    MakePanic()
}

func main() {
    Survive()
}

输出如下:
制造一个panic
111
我来拯救你这个panic

deferred函数在panic的情况下,仍能被执行。

三 defer 避 “坑” 指南

1 哪些函数可以作为deferred函数
方法和函数与defer无条件的结合,但有返回值的函数或方法,返回值会在deferred函数被调用的时候丢弃。

2 记得defer是后进先出的顺序执行的

3 defer也是有性能损失的,为保证defer对整个应用的影响,尽量多进行测试,适当的使用defer。

image


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:.container .card .information strong

查看原文:16.defer 让代码更清晰

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

348 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传