本文视频地址
一 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。