多个延迟vs延迟匿名函数

问题描述 投票:16回答:2

发出多个依赖于顺序的defer语句,或者推迟打包逻辑的匿名函数,是更安全还是更惯用?

例子:

defer os.Remove(tempFile.Name())
defer tempFile.Close()

在上面的情况中,语法是最小的,但是延迟的顺序与要执行的逻辑相反。

在下面的情况下,有更多的行,更多的“语法”,但逻辑是一个更自然的顺序:

defer func() {
    tempFile.Close()
    os.Remove(tempFile.Name())
}()

哪一个使用?

go resource-cleanup
2个回答
18
投票

在此示例中,匿名函数更易于阅读,尤其是在添加错误处理之后。

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)
  }
}()

如果您有多个资源,那么多个defers通常是合适的。


0
投票

如果您有多个资源,那么多个延迟通常是合适的。

但在这种情况下,请考虑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)
© www.soinside.com 2019 - 2024. All rights reserved.