发出多个依赖于顺序的defer
语句,或者推迟打包逻辑的匿名函数,是更安全还是更惯用?
例子:
defer os.Remove(tempFile.Name())
defer tempFile.Close()
在上面的情况中,语法是最小的,但是延迟的顺序与要执行的逻辑相反。
在下面的情况下,有更多的行,更多的“语法”,但逻辑是一个更自然的顺序:
defer func() {
tempFile.Close()
os.Remove(tempFile.Name())
}()
哪一个使用?
在此示例中,匿名函数更易于阅读,尤其是在添加错误处理之后。
f, err := ioutil.TempFile("", "prefix")
if err != nil {
log.Println("creating temp file:", err)
return
}
defer func() {
err := f.Close()
if err != nil {
log.Println("close:", err)
}
err = os.Remove(f.Name())
if err != nil {
log.Println("remove:", err)
}
}()
如果您有多个资源,那么多个defer
s通常是合适的。
如果您有多个资源,那么多个延迟通常是合适的。
但在这种情况下,请考虑Go 1.13(Q4 2019),因为它确实整合了go issue 14939: "runtime: defer is slow"和go issue 6980: "cmd/compile: allocate some defers in stack frames"的修复程序
见Go CL 171758: "cmd/compile,runtime: allocate defer records on the stack"
当在函数体中最多执行一次延迟时,我们可以在堆栈而不是堆上为它分配延迟记录。
这应该更快地推迟这样(这是很常见的)。
此优化适用于cmd / go二进制文件中370个静态延迟站点中的363个。
name old time/op new time/op delta Defer-4 52.2ns ± 5% 36.2ns ± 3% -30.70% (p=0.000 n=10+10)