Привет, товарищ интернет-пользователь, прежде чем мы начнем, в этой статье предполагается, что у вас есть следующие предварительные условия.
- Вы знаете о функциях в go
- иметь представление о локальном и глобальном масштабе
- Настройте свой vsc для go-lang, потому что это будет восхитительный опыт с автозаполнением, линтингом и автоматическим импортом.
С этим покончено, перейдем к главному вопросу, юный падаван.
Что такое отсрочка?
Чтобы мы были на одной странице, вы всегда используете ключевое слово defer
при вызове функции. Теперь отсрочка означает, что выполнение отложенной функции откладывается до конца окружающей функции.
- В приведенном выше коде отложенной функцией является
fmt.Println("Two")
, поэтому эта функция будет выполняться после завершения выполнения окружающей функции, в нашем случае это было просто напечататьfmt.Println("Three")
, как только это закончится, отложенная функция будет выполнена. - Следует отметить, что если у вас есть несколько ключевых слов
defer
в одной функции, они будут выполняться в порядке «первым пришел — последним», или в порядкеFILO
, простыми словами, в обратном порядке, в котором они были отложены. - Давайте немного сойдем с ума на секунду и добавим ключевое слово
defer
ко всему, что вы видите, попробуйте предсказать результат.
- В приведенном выше коде, поскольку все отложено, ничего не выполняется до тех пор, пока элемент управления не достигнет строки 8, так как
fmt.Println("Four")
является последней отложенной функцией, она выполняется первой, другими словами, это не имеет большого значения, если вы хотите отложить функцию непосредственно перед завершением окружающей функции. - И так как
fmt.Println("One")
было отложено первым, оно было выполнено последним. - Следует отметить, что отложенная функция принадлежит окружающей функции, а не области действия блока, поэтому, если вы отложили функцию в блоке
if
или в циклеfor
, отложенная функция функция всегда будет выполняться после завершения окружающей функции, а не перед циклом или оператором if.
Хорошо, но что, если я хочу что-то вернуть из отложенной функции?
- ну, вы не можете этого сделать, ваша функция должна быть такой, которая ничего не возвращает, или вы можете получить возврат и отложить его, но вам придется игнорировать возвращаемое значение.
- Но в Go есть функция под названием named return, что делает вещи немного интереснее.
- В строке выше, когда функция создается,
returnVal
равно 0, мы откладываем анонимную функцию, поэтому мы переходим к строке 15, тамreturnVal
становится -1, наконец, наша функция запускается, и мы перезаписываемreturnVal
как 1000, и мы возвращаемся это значение.
Хорошо, теперь для закрытия
- Замыкания — это значения функций, которые ссылаются на переменные, находящиеся вне рассматриваемой функции.
- Этот фрагмент кода беззастенчиво украден из документации, потому что на самом деле его так легко понять.
- что следует отметить: несмотря на то, что
sum
определено вне области действия анонимной функции возврата, переменнаяsum
связана с ней, с другой копией каждый раз, когдаadder()
вызывается, чтобы быть точным. - здесь, поскольку каждый экземпляр анонимной функции, которая оказывается
pos(i int)
иneg(i int)
, может быть вызван с другим параметром, они оба имеют свою собственную переменнуюsum
под капотом, что позволяет им иметь разные выходные данные, как показано.
давайте смешать вещи!!
- это становится более интересным, когда вы откладываете анонимную функцию в цикле, так как функция теряет свое значение за пределами цикла, компилятору приходится отслеживать вызовы отложенной функции разными способами, смотрите ниже.
- здесь vsc показывает, что переменная
index
будет захвачена, то есть адресное пространство, на которое ссылаетсяindex
, будет привязано к функции, поэтому в выводе мы видим, чтоcaptured index is 4
печатается 4 раз, это связано с концепцией закрытия. - но в другом цикле, в строке 17, мы сохраняем значение, которое
index
содержит вместе с функцией, как указано в документах здесь,
Каждый раз, когда выполняется оператор defer, значение функции и параметры вызова оцениваются как обычно и сохраняются заново, но фактическая функция не вызывается.
Надеюсь, вы узнали что-то из этой статьи, если есть какие-либо неправильные предположения, сделанные от моего имени, пожалуйста, сообщите :), ничто не порадует меня больше, чем развеять мои неточные представления.
А пока я просто свяжу то, что помогло мне написать эту статью.
- еще одна крутая статья про отсрочку
- Обсуждение комбинатора Y было весьма познавательным
- Я мог или не мог взять что-то из этого вопроса о переполнении стека
Спасибо за чтение и желаю вам отличного дня 😁
Первоначально опубликовано на https://toothsy.hashnode.dev.