Оператор defer в языке Go

Оператор defer служит для планирования вызова функции, то есть речь идет, по сути, об отложенной функции. Это довольно необычный, но эффективный способ справиться с ситуациями, когда ресурсы важно освободить вне зависимости от того, какой именно путь принимает функция для возврата. Традиционный пример -- разблокировка мьютекса либо закрытие файла.

Давайте посмотрим, как это работает:

Отсрочка вызова функции, той же Close, имеет следующие плюсы:

  1. Гарантируется, что вы не забудете закрыть файл (такую ошибку легко допустить, если вы позже выполните редактирование функции для добавления нового пути возврата).
  2. Отсрочка вызова означает, что закрытие будет находиться рядом с открытием, а это гораздо понятнее, чем помещение в конец функции.

Аргументы для отложенной функции (включают получателя, когда функция является методом) оцениваются, если выполняется defer, а не в том случае, когда выполняется вызов (call). Такое положение вещей поможет избежать лишних забот о переменных, которые меняют значения в случае выполнения функции, что тоже значит, что отложить исполнение нескольких функций может лишь одно место отложенного вызова. Рассмотрим простой пример:

Важно отметить, что отложенные функции выполняются в соответствии с LIFO (last-in-first-out), следовательно, данный код вызовет "4 3 2 1 0" для печати после возврата из функции. Также можно написать пару простых трассировок:

Еще момент: аргументы отложенных функций оцениваются во время выполнения defer. Например, процедура трассировки способна установить аргумент для процедуры отслеживания. Смотрим пример ниже:

Будет напечатано следующее:

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

По материалам https://golang-blog.blogspot.com/.