иди изучай заметки, чтобы разобраться с функцией задержки отсрочки

Go
иди изучай заметки, чтобы разобраться с функцией задержки отсрочки

Пересматривайте старое и изучайте новое, не забывая об основах задержки

go-error-defer-learn-from-old.jpg

A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.

функция задержкиПродолжительностьОбычно бывает три ситуации:

  • Когда окружающая функция встречает возврат
func funcWithMultipleDeferAndReturn() {
    defer fmt.Println(1)
    defer fmt.Println(2)
    fmt.Println(3)
    return
    fmt.Println(4)
}

результат операции:3 2 1 .

«Технологическая станция «Снежная мечта»»:defer fmt.Println(1)а такжеdefer fmt.Println(2)Два утверждения существуют из-за предыдущегоdeferключевые слова, поэтому обаэто задерживаетсяк нормальному заявлениюreturnдо. когда несколькоdeferКогда все операторы задержаны, задержанные операторы выполняются в обратном порядке, что очень похоже на структуру данных.куча(первым пришел, последним вышел) Таким образом, выводить последовательноfmt.Println(3) ,defer fmt.Println(2) ,defer fmt.Println(1) .

  • В конце окружающего тела функции
func funcWithMultipleDeferAndEnd() {
    defer fmt.Println(1)
    defer fmt.Println(2)
    fmt.Println(3)
}

результат операции:3 2 1 .

«Технологическая станция Snow Dream»: СравнитеfuncWithMultipleDeferAndReturnПример проще, хотя функция окруженияfuncWithMultipleDeferAndEndне показывает заявлениеreturnоператор, но не забудет выполнить отложенный оператор, когда функция завершит работу.fmt.Println(3)После выполнения программа не завершается немедленно, а немедленно выполняет отложенный оператор.defer fmt.Println(2)а такжеdefer fmt.Println(1).

  • Текущая сопрограмма паникует
func funcWithMultipleDeferAndPanic() {
    defer fmt.Println(1)
    defer fmt.Println(2)
    fmt.Println(3)
    panic("panic")
    fmt.Println(4)
}

результат операции:3 2 1 .

«Технологическая станция Snow Dream»: иfuncWithMultipleDeferAndReturnПример чем-то похож, за исключением того, что исходныйreturnФраза заменена наpanic("panic"), Мы знаем об отложенных операторахdefer fmt.Println(1)а такжеdefer fmt.Println(2)Он точно задержится, поэтому не будет выведен первым1,2но казнен первымfmt.Println(3), следующим шагом будет встречаpanic("panic"), в это время не нужно паниковать, пусть существующиеdeferОператоры выполняются первыми! в то же время,deferвыполняется в обратном порядке, поэтому выведите сначалаdefer fmt.Println(2)вывод сноваdefer fmt.Println(1), наконец завершить миссию, славно повесить трубку, как дляfmt.Println(4)нельзя казнить!

Подробное толкование этого предложения см.Интерпретация примечаний к изучению Что такое функция задержки отсрочки, см. пример исходного кодаsnowdreams1006/learn-go/tree/master/error

Если вы действительно пытаетесь понятьdeferизвремя исполнения, лучше посмотретьассемблерный кодКонкретная реализация, рекомендую большой пареньотложить ключевое слово

оdeferОбъяснения, связанные с ключевыми словами, выдержки из них следующие:

когда функция содержитdeferоператор, ассемблерный код:

с вызов runtime.deferreturn, добавить хх сп вернуть

goroutineВ структуре управления есть табличная записьdefer,передачаruntime.deferprocпонадобитсяdeferВыражения записываются в таблицу, а в вызовеruntime.deferreturn, это будет последовательно изdeferТаблица извлекается из стека и выполняется.

Однако было бы проще понять семантически, спросите себя, зачем вам нужноdeferКлючевые слова, какую проблему он решает?

go-error-defer-question.png

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

короче,deferКлючевое слово — это логика кода, обеспечивающая выполнение программы независимо от того, является ли она нормальной.returnвсе еще аварияpanic, если функция окружения существуетdeferКлючевым словом является обеспечение того, чтобы функция задержки выполнялась!

когда их несколькоdeferКогда используется ключевое слово, это означает, что есть несколько срочных задач, которые необходимо обработать, и время ограничено, конечно, приоритетным выполнением является то, что находится ближе всего к точке аварии,returnилиpanicЧем дальше, тем позже казнь.

такНа всякий случай и принцип близостипонятьdeferЛучший способ рассчитать время: в случае пожара в один прекрасный день первой реакцией, естественно, будет спасение людей поблизости!

go-error-defer-fire-and-save.jpg

Что поддерживать, а что нет

The expression must be a function or method call; it cannot be parenthesized. Calls of built-in functions are restricted as for expression statements.
  • Вызовы функций поддержки
func funcCallWithDefer() {
    fmt.Println("funcInvokeWithDefer function is called")
}

func TestFuncCallWithDefer(t *testing.T) {
    // 「雪之梦技术驿站」: defer 语句可以是函数调用.
    fmt.Println(" 「雪之梦技术驿站」: defer 语句可以是函数调用.")

    defer funcCallWithDefer()

    fmt.Println("TestFuncInvokeWithDefer function call has ended")
}
  • Вызовы методов поддержки
type Lang struct {
    name    string
    website string
}

func (l *Lang) ToString() {
    fmt.Printf("Lang:[name = %s,website = %s] \n", l.name, l.website)
}

func TestMethodCallWithDefer(t *testing.T) {
    // 「雪之梦技术驿站」: defer 语句也可以是方法调用.
    fmt.Println(" 「雪之梦技术驿站」: defer 语句也可以是方法调用.")

    var l = new(Lang)
    l.name = "Go"
    l.website = "https://snowdreams1006.github.io/go/"

    defer l.ToString()

    fmt.Println("TestMethodCallWithDefer method call has ended")
}
  • нельзя заключать в скобки

go-error-defer-parenthesized-fail.png

  • Встроенные функции так же ограничены, как и выражения
Имя функции иллюстрировать иллюстрировать
close закрыть канал Только для канала связи
delete удалить экземпляр с карты операция карты
len Возвращает длину строк, срезов и массивов Доступны в различных типах
cap обратная способность Доступны в различных типах
new выделение памяти для различных типов
make выделение памяти только для чан/срез/карта
copy копировать фрагмент операция среза
append добавить фрагмент операция среза
panic Сообщить о проблемах во время выполнения механизм обработки исключений
recover Обработка проблем во время выполнения механизм обработки исключений
print Встроенная функция печати. В основном используется для отладки, когда fmt не вводится, в реальных условиях рекомендуется использовать стандартную библиотеку fmt
println Встроенная функция печати. В основном используется для отладки, когда fmt не вводится, в реальных условиях рекомендуется использовать стандартную библиотеку fmt
complex Построить сложный тип сложные операции
real Извлечь действительную часть комплексного числа сложные операции
imag Извлечь мнимую часть комплексного числа сложные операции
func TestBuiltinFuncCallWithDefer(t *testing.T) {
    // 「雪之梦技术驿站」: defer 语句不可以被括号包裹.
    fmt.Println(" 「雪之梦技术驿站」: defer 语句不可以被括号包裹.")

    arr := new([10]int)
    arr[4] = 5
    arr[7] = 8

    // defer discards result of len(arr)
    defer len(arr)
    defer println("Calls of built-in functions are restricted as for expression statements.")

    fmt.Println("TestBuiltinFuncCallWithDefer function call has ended")
}

Буквально понимать задержку

Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred. That is, if the surrounding function returns through an explicit return statement, deferred functions are executed after any result parameters are set by that return statement but before the function returns to its caller. If a deferred function value evaluates to nil, execution panics when the function is invoked, not when the "defer" statement is executed.

Ударь змею и ударь семь дюймов

go-error-defer-emphasis.jpeg

Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.

Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.

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

func trace(funcName string) func(){
    start := time.Now()
    fmt.Printf("function %s enter at %s \n",funcName,start)

    return func(){
        fmt.Printf("function %s exit at %s(elapsed %s)",funcName,time.Now(),time.Since(start))
    }
}

func foo(){
    fmt.Printf("foo begin at %s \n",time.Now())

    defer trace("foo")()
    time.Sleep(5*time.Second)

    fmt.Printf("foo end at %s \n",time.Now())
}

func TestFoo(t *testing.T) {
    foo()
}

traceфункция реализованафункция синхронизациифункция, в то время какfooФункция является окружающей функцией для демонстрацииdeferлогика ключевых слов,TestFooэто тестовая функция, которая выводит результат теста.

Результаты теста следующие:

=== RUN TestFoo foo begin at 2019-11-18 23:12:38.519097 +0800 CST m=+0.000735902 function foo enter at 2019-11-18 23:12:38.519287 +0800 CST m=+0.000926011 foo end at 2019-11-18 23:12:43.524445 +0800 CST m=+5.005934027 function foo exit at 2019-11-18 23:12:43.524549 +0800 CST m=+5.006038281(elapsed > 5.005112612s)--- PASS: TestFoo (5.01s) PASS

Process finished with exit code 0

Если вы попытаетесь объяснить приведенные выше беговые результаты в это время, очень жаль, что вы потерпели неудачу!

go-error-defer-foo-explain-fail.jpeg

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

A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.

Но если вы будете следовать этому предложению, чтобы объяснить текущие результаты этого примера, это, очевидно, необъяснимо!

func foo(){
    fmt.Printf("foo begin at %s \n",time.Now())

    defer trace("foo")()
    time.Sleep(5*time.Second)

    fmt.Printf("foo end at %s \n",time.Now())
}

func TestFoo(t *testing.T) {
    foo()
}

еслиdefer trace("foo")()Функция задержки действительно задерживается до тех пор, покадо конца тела функции, то вышеfoo()Функция должна быть эквивалентна этой форме:

func fooWithoutDefer(){
    fmt.Printf("foo begin at %s \n",time.Now())

    time.Sleep(5*time.Second)

    fmt.Printf("foo end at %s \n",time.Now())

    trace("foo")()
}

func TestFooWithoutDefer(t *testing.T) {
    fooWithoutDefer()
}

Но дляfooWithoutDeferРезультат выполнения функции прямо бьет в лицо:

=== RUN TestFooWithoutDefer foo begin at 2019-11-19 11:44:20.066554 +0800 CST m=+0.001290523 foo end at 2019-11-19 11:44:25.068724 +0800 CST m=+5.003312582 function foo enter at 2019-11-19 11:44:25.068796 +0800 CST m=+5.003384341 function foo exit at 2019-11-19 11:44:25.068847 +0800 CST m=+5.003435185(elapsed 51.196µs)--- PASS: TestFooWithoutDefer (5.00s) PASS

Process finished with exit code 0

Видно, что функция задержки на самом деле не простая, если хотите разобратьсяdeferКлючевое слово должно продолжать читать, прежде чем это станет возможным!

go-error-defer-foo-result-diff.png

Это тоже мое самое большое сомнение Мое подсознание говорит мне: пока я не могу толком понятьEach time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.Смысл этого предложения никогда не может быть полностью понятdeferКлючевые слова!

путем прямого обменаdeferРасположение утверждения не объясняет результаты теста, но сообщает намdeferОператоры — это не просто отложенное выполнение.

Любая функция будет более или менее зависеть от соответствующей среды выполнения,deferФункции задержки не являются исключением, в этом примереdefer trace("foo")()функция задержкиtrace("foo")Возвращаемое значение функции - это функция, тогдаtrace("foo")()эквивалентно немедленному выполнению возвращающей функции, поэтому проблема может возникнуть вtrace("foo")функция, так что давайте продолжим смотреть на нее!

func foo(){
    fmt.Printf("foo begin at %s \n",time.Now())

    defer trace("foo")()
    time.Sleep(5*time.Second)

    fmt.Printf("foo end at %s \n",time.Now())
}

func trace(funcName string) func(){
    start := time.Now()
    fmt.Printf("function %s enter at %s \n",funcName,start)

    return func(){
        fmt.Printf("function %s exit at %s(elapsed %s)",funcName,time.Now(),time.Since(start))
    }
}

1. foo begin at 2019-11-19 14:06:42.385982 +0800 CST m=+0.000943615подразумевая, что он начал входитьfoo()Внутри функции следующийfunction foo enter at 2019-11-19 14:06:42.38623 +0800 CST m=+0.001191025означает, что функция не выполняетсяtime.Sleep(5*time.Second)а прямо вdefer trace("foo")()Внутри оператора видимые функции по-прежнему выполняются последовательно, ноtrace(funcName string) func()Функция вернет функцию внутри функции, и возвращаемое значение функции в это время не выполняется, потому что в это время нет вывода журнала.

такtrace(funcName string) func()Функция должна была выполниться, затем вернуться на предыдущий уровень и вернуться к основной функцииfoo()только что встретилtime.Sleep(5*time.Second)отдых5sзаявление, поэтому выполнениеfmt.Printf("foo end at %s \n",time.Now())Время вывода оператора равно разнице между последним предложением и последним предложением.5s .

foo end at 2019-11-19 14:06:47.391581 +0800 CST m=+5.006394415После вывода это означаетfoo()Функция выполняется до конца объемлющей функции, и в этот момент, согласно первому предложению оператора задержки, мы знаем, что пришло время выполнить настоящую логику задержки.

Итак, следующая фразаtrace("foo")()Функция возвращает значение вызова, которое выводитfunction foo exit at 2019-11-19 14:06:47.391706 +0800 CST m=+5.006518615(elapsed 5.005327927s)--- PASS: TestFoo (5.01s)

В этот момент выполняется функция задержки, а также выводится функция модульного тестирования.PASS .

=== RUN   TestFoo
foo begin at 2019-11-19 14:06:42.385982 +0800 CST m=+0.000943615 
function foo enter at 2019-11-19 14:06:42.38623 +0800 CST m=+0.001191025 
foo end at 2019-11-19 14:06:47.391581 +0800 CST m=+5.006394415 
function foo exit at 2019-11-19 14:06:47.391706 +0800 CST m=+5.006518615(elapsed 5.005327927s)--- PASS: TestFoo (5.01s)
PASS

Благодаря приведенному выше анализу можно понять, что функция задержки также нуждается в среде выполнения, а среда выполнения зависит от определенияdeferСоответствующая среда во время заявления, которая является функцией задержкиЭтап подготовкиИливставить в стек.

Когда тело объемлющей функции возвращается или достигает конца тела объемлющей функции или возникает ошибка, объемлющая функция вызывает существующую функцию задержки, которая является частью функции задержки.этап выполненияИлипоп.

  • Есть ли функция задержки,Последовательное исполнениефункциональная логика
  • Операция push на этапе подготовки будет работать нормально, нофункция не будет вызываться
  • Операция pop в фазе выполнения находится вФункция будет вызвана, когда придет время

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

Однажды обычные люди и особые люди делали покупки в торговом центре, когда вспыхнул пожар, ближайшие пожарные быстро поспешили спасти людей.Задача была только одна: то есть следить заПринцип близости для быстрого спасенияВсе особые группы, потому что все эти особые группы — головы и лица, и у каждого свой темперамент и индивидуальность.

Звезда А: Я взял ограниченную серию перед тем, как пойти в торговый центр.LVМешок, я тоже его достану! Фу Эрдай Б: Перед тем, как войти в торговый центр, я пообещал своей маленькой подружке купить ему подарок. Это адрес шкафчика. Не забудьте вернуть подарок! Нувориш С: У меня в торговом центре есть сейф, в котором хранится много золотых слитков, надо достать его для меня!

Пожарный был очень беспомощен и ругался в душе: это вопрос жизни и смерти, о чем еще заботиться!

Однако жалоба есть жалоба, потому что забота об этих особых группах, то есть ни малейшего пренебрежения, может только это сделать, и, наконец, спасла их всех!

А для декларацииdeferПараметр был передан, когда инструкция, дождаться выполненияdeferПри вызове значение параметра только что, иGoПередача параметров в языке может быть толькопередать по значению, так что хотя он все еще выглядит как тот мешок, он на самом деле изменился, и здесь он не особенно точен! B для декларацииdeferПараметр передается, когда оператор является не конкретным значением, а ссылкой, когда выполнениеdeferКогда дело доходит до логики, она будет следовать картинке, поэтому, хотя бумажка с паролем от шкафчика дана, подарок в шкафчике, наконец, вынут. C для декларацииdeferКогда ничего не передается, нет входного параметра, но выполнениеdeferВ заявлении встречается необходимость доступа к закрывающей функции.В это время функция задержки будет расширять диапазон поиска и искать вверх, пока не найдет хранилище торгового центра.

  • Нулевые зависимости и никаких забот
func deferWithoutParams() {
    // 2 1
    defer fmt.Println(1)
    fmt.Println(2)
}

«Технологическая станция Snow Dream»: нет никакой зависимости при входе в стек и нет проблем при выходе из него, очень простой и интуитивно понятный вывод.2 1 .

  • уход за собой
func deferWithValueParams() {
    x := 10
    defer func(n int) {
        // 10
        fmt.Println(n)
    }(x)
    x++
}

«Технологическая станция Snow Dream»: есть параметры-значения при проталкивании в стекfunc(n int)(10), значение выходного параметра должно быть выведено при извлечении из стека, иfmt.Println(n)ВовлеченныйnПросто сохранено в среде стека, поэтому подождите, покаdeferWithValueParamsВывод после запуска до конца функции представляет собой кешированную копию.10 .

Если анонимный вызов функции в это время неnноx, а переменнаяxНе существует в среде стека, в настоящее время он будет продолжать расширять область поискаdeferWithValueParamsЕсть ли у функции переменныеxобъявления, найденные в этом примереx=11.

func deferWithOuterParams() {
    x := 10
    defer func(n int) {
        // 11
        fmt.Println(x)
    }(x)
    x++
}
  • я не могу отпустить
func deferWithReferParams() {
    x := 10
    defer func(n *int) {
        // 11
        fmt.Println(*n)
    }(&x)
    x++
}

«Технологическая станция Snow Dream»: при добавлении в стек это уже не значение, а адрес, поэтому при выходе из стека он будет следовать карте, чтобы найти значение, соответствующее адресу, который11 .

Я считаю, что приведенный выше случай должен помочь читателям понятьdeferНекоторые примечания к предложению?

Стек на этапе подготовки отложенной функции будет собирать зависимости от среды, необходимые для запуска функции, такие как значение входного параметра.После завершения сбора, даже если внешний мир изменит значение, это не повлияет отложенная функция, потому что отложенная функция использует кэшированную копию!

Поппинг будет обратным

Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred.

И наоборот, отложенные функции вызываются в порядке, обратном отложенному, до того, как объемлющая функция вернется.

func TestFuncWithMultipleDefer(t *testing.T) {
    // 「雪之梦技术驿站」: 猜测 defer 底层实现数据结构可能是栈,先进后出.
    t.Log(" 「雪之梦技术驿站」: 猜测 defer 底层实现数据结构可能是栈,先进后出.")

    // 3 2 1
    defer t.Log(1)
    defer t.Log(2)
    t.Log(3)
}

«Технологическая станция Snow Dream»: операция всплывания на этапе выполнения будет выполнять несколько операций в обратном порядке.deferфункция задержки, поэтому выход3 2 1 .

своевременная установка дождя

That is, if the surrounding function returns through an explicit return statement, deferred functions are executed after any result parameters are set by that return statement but before the function returns to its caller.

Когда объемлющая функция передается явным образомreturnКогда возвращается оператор return,deferФункция задержки будет вresult parametersПосле назначения параметра результата и после функцииreturnВыполнить перед возвращением.

Согласно этому предложению можно разобрать следующий код:

defer yyy
return xxx

вreturn xxxЭто эквивалентно разделению на два шага и вставке их вовремя перед окончательным возвратом.deferЛогика выполнения инструкции следующая:

1. result parameters = xxx
2. 调用 defer 函数
3. return

Точно так же проиллюстрируем на примере:

func deferWithExplicitReturn() (result int) {
    defer func() {
        // 2. before : result = 10
        fmt.Printf("before : result = %v\n", result)

        result++

        // 3. after : result = 11
        fmt.Printf("after : result = %v\n", result)
    }()

    result = 10

    // 1. return : result = 10
    fmt.Printf("return : result = %v\n", result)

    return result
}

оdeferПорядок выполнения и результаты вывода отложенных функций больше не сложны, и теперь основное внимание уделяетсяdeferWithExplicitReturn()Какое значение возвращается после завершения работы функции?10все еще11 .

func TestDeferWithExplicitReturn(t *testing.T) {
    // TestDeferWithExplicitReturn result = 11
    fmt.Printf("TestDeferWithExplicitReturn result = %d\n",deferWithExplicitReturn())
}

«Технологическая станция Snow Dream»: выводятся результаты испытаний.11, очевидно, это потому, что функция задержки выполняется внутриresult++В конечном итоге операция влияет на возвращаемое значение внешней функции.

Если приведенный выше пример изменить, следующий код ясно увидит, почему это влияет на возвращаемое значение.

func deferWithExplicitReturnByExplain() (result int) {
    result = 10

    // 1. return : result = 10
    fmt.Printf("return : result = %v\n", result)
    
    func() {
        // 2. before : result = 10
        fmt.Printf("before : result = %v\n", result)

        result++

        // 3. after : result = 11
        fmt.Printf("after : result = %v\n", result)
    }()

    return
}

«Технологическая станция Snow Dream»: будет включена функция задержки.returnПеред возвратом есть возможность изменить возвращаемое значение.Здесь демонстрируется логика своевременной вставки дождя.Выходной результат остается неизменным.11.

go-error-defer-deferWithExplicitReturnByExplain-result.png

Вот несколько примеров, подумайте сами

func surroundingFuncEvaluatedNotInvoked(init int) int {
    fmt.Printf("1.init=%d\n",init)

    defer func() {
        fmt.Printf("2.init=%d\n",init)

        init ++

        fmt.Printf("3.init=%d\n",init)
    }()

    fmt.Printf("4.init=%d\n",init)

    return init
}

func noDeferFuncOrderWhenReturn() (result int) {
    func() {
        // 1. before : result = 0
        fmt.Printf("before : result = %v\n", result)

        result++

        // 2. after : result = 1
        fmt.Printf("after : result = %v\n", result)
    }()

    // 3. return : result = 1
    fmt.Printf("return : result = %v\n", result)

    return 0
}


func deferFuncWithAnonymousReturnValue() int {
    var retVal int
    defer func() {
        retVal++
    }()
    return 0
}

func deferFuncWithNamedReturnValue() (retVal int) {
    defer func() {
        retVal++
    }()
    return 0
}

«Технологическая станция Snow Dream»: если вы не можете сразу увидеть ответ, вы можете скопировать его в редактор и запустить напрямую, а затем подумать, почему.

ошибка при звонке

If a deferred function value evaluates to nil, execution panics when the function is invoked, not when the "defer" statement is executed.

Если функция задержкиnil, исключение ошибки возникает при вызове функцииpanicвместоdeferОшибка возникает при выполнении инструкции.

func deferWithNil() func() {
    return nil
}

func TestDeferWithNil(t *testing.T) {
    fmt.Println("begin exec deferWithNil()()")

    defer deferWithNil()()

    fmt.Println("end exec deferWithNil()()")
}

go-error-defer-deferWithNil-result.png

Огласите ответ и полный текст резюме

В прошлой статье я оставил два небольших вопроса, я считаю, что каждый, кто увидит эту статью, сможет самостоятельно ее заполнить и объяснить, верно?

Ниже вопросы и ответы!

func deferFuncWithAnonymousReturnValue() int {
    var retVal int
    defer func() {
        retVal++
    }()
    return 0
}

func deferFuncWithNamedReturnValue() (retVal int) {
    defer func() {
        retVal++
    }()
    return 0
}

func TestDeferFuncWhenReturn(t *testing.T) {
    // 0
    t.Log(deferFuncWithAnonymousReturnValue())
    // 1
    t.Log(deferFuncWithNamedReturnValue())
}

«Технологическая станция «Снежная мечта»»:deferFuncWithAnonymousReturnValue()Функция не имеет явного параметра возвращаемого значения, иdeferFuncWithNamedReturnValue()функция была объявлена(retVal int)Возвращает значение, так как функции отсрочки не влияют на безымянные функции.

Благодаря этой статье мы узнали время выполнения функции задержки и некоторые детали.Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.Эта фраза определенновысший приоритет!

Короче говоря, отложенная функция будет собирать копию соответствующего назначения параметра при его объявлении.вставить в стек, когда придет время, ищите соответствующие параметры среды из среды стека. Если вы не можете ее найти, расширьте область, чтобы узнать, содержит ли внешняя функция требуемые переменные. Процесс выполнения - это функция задержки.поп.

Есть пожарный, который несет особую ответственность за безопасность торгового центра.Каждый день в торговый центр входит и выходит много людей, и всегда есть несколько важных людей, которые приходят в торговый центр за покупками.Внезапно в один прекрасный день вспыхнул пожар. вышел, и все запаниковали...

Что сделал этот пожарный, чтобы обезопасить важных людей и защитить их от материального ущерба?

go-error-defer-panic.png

Пожалуйста, добавьте свой ответ, спасибо за прочтение и внимание, увидимся в следующем разделе~

Читать расширения и справочную документацию

Если вы считаете, что эта статья полезна для вас, добро пожаловатьСтавь лайк и оставляй сообщениеСкажи мне, что твоя поддержка является движущей силой для меня, чтобы продолжать творить, кстати, возможно, ты захочешь обратить внимание на мой личный публичный аккаунт."Технологическая станция «Снежная мечта»», регулярно обновляйте качественные статьи!

雪之梦技术驿站.png