Несколько отложенных и отложенных анонимных функций

Безопаснее или идиоматичнее выдавать несколько defer операторы, которые зависят от порядка, или отложить анонимную функцию, которая упаковывает логику?

Примеры:

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

В приведенном выше случае синтаксис минимален, но порядок отложений обратен логике, которая должна быть выполнена.

В приведенном ниже примере больше строк, больше "синтаксиса", но логика в более естественном порядке:

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

Какой использовать?

1 ответ

Решение

В этом примере анонимную функцию легче читать, особенно после добавления обработки ошибок.

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с, как правило, уместно.

Если у вас есть несколько ресурсов, то обычно подходит несколько отсрочек.

Но в этом случае рассмотрим Go 1.13 (Q4 2019), поскольку в нем исправлено исправление проблемы go 14939: "runtime: defer is slow" и проблема go 6980: "cmd/compile: выделение некоторых отложений в кадрах стека"

См. Go CL 171758: "cmd/compile, время выполнения: выделить отложенные записи в стеке"

Когда defer выполняется не более одного раза в теле функции, мы можем разместить запись defer для него в стеке, а не в куче.

Это должно сделать такие отсрочки (которые очень распространены) быстрее.

Эта оптимизация применяется к 363 из 370 сайтов статической отсрочки в двоичном файле cmd/go.

name     old time/op  new time/op  delta
Defer-4  52.2ns ± 5%  36.2ns ± 3%  -30.70%  (p=0.000 n=10+10)
Другие вопросы по тегам