Пересматривайте старое и изучайте новое, не забывая об основах задержки
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
Ключевые слова, какую проблему он решает?
Однажды понялdefer
Намерение реализации ключевого слова, то естественно угадать порядок выполнения, так зачем вникать в детали реализации?
короче,defer
Ключевое слово — это логика кода, обеспечивающая выполнение программы независимо от того, является ли она нормальной.return
все еще аварияpanic
, если функция окружения существуетdefer
Ключевым словом является обеспечение того, чтобы функция задержки выполнялась!
когда их несколькоdefer
Когда используется ключевое слово, это означает, что есть несколько срочных задач, которые необходимо обработать, и время ограничено, конечно, приоритетным выполнением является то, что находится ближе всего к точке аварии,return
илиpanic
Чем дальше, тем позже казнь.
такНа всякий случай и принцип близостипонятьdefer
Лучший способ рассчитать время: в случае пожара в один прекрасный день первой реакцией, естественно, будет спасение людей поблизости!
Что поддерживать, а что нет
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")
}
- нельзя заключать в скобки
- Встроенные функции так же ограничены, как и выражения
Имя функции | иллюстрировать | иллюстрировать |
---|---|---|
close | закрыть канал | Только для канала связи |
delete | удалить экземпляр с карты | операция карты |
len | Возвращает длину строк, срезов и массивов | Доступны в различных типах |
cap | обратная способность | Доступны в различных типах |
new | выделение памяти | для различных типов |
make | выделение памяти | только для чан/срез/карта |
copy | копировать фрагмент | операция среза |
append | добавить фрагмент | операция среза |
panic | Сообщить о проблемах во время выполнения | механизм обработки исключений |
recover | Обработка проблем во время выполнения | механизм обработки исключений |
Встроенная функция печати. | В основном используется для отладки, когда 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.
Ударь змею и ударь семь дюймов
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
Если вы попытаетесь объяснить приведенные выше беговые результаты в это время, очень жаль, что вы потерпели неудачу!
Помните официальную документацию о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
Ключевое слово должно продолжать читать, прежде чем это станет возможным!
Это тоже мое самое большое сомнение Мое подсознание говорит мне: пока я не могу толком понять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
.
Вот несколько примеров, подумайте сами
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()()")
}
Огласите ответ и полный текст резюме
В прошлой статье я оставил два небольших вопроса, я считаю, что каждый, кто увидит эту статью, сможет самостоятельно ее заполнить и объяснить, верно?
Ниже вопросы и ответы!
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.
Эта фраза определенновысший приоритет!
Короче говоря, отложенная функция будет собирать копию соответствующего назначения параметра при его объявлении.вставить в стек, когда придет время, ищите соответствующие параметры среды из среды стека. Если вы не можете ее найти, расширьте область, чтобы узнать, содержит ли внешняя функция требуемые переменные. Процесс выполнения - это функция задержки.поп.
Есть пожарный, который несет особую ответственность за безопасность торгового центра.Каждый день в торговый центр входит и выходит много людей, и всегда есть несколько важных людей, которые приходят в торговый центр за покупками.Внезапно в один прекрасный день вспыхнул пожар. вышел, и все запаниковали...
Что сделал этот пожарный, чтобы обезопасить важных людей и защитить их от материального ущерба?
Пожалуйста, добавьте свой ответ, спасибо за прочтение и внимание, увидимся в следующем разделе~
Читать расширения и справочную документацию
- Defer_statements
- Built-in_functions
- Встроенные функции в спецификации языка Go
- Быстрый старт Go Language: встроенные функции(6)
- Вы знаете яму отсрочки?
- Особенности отложенного языка Golang подробное объяснение.md
- Простое решение Голанга для нежной ловушки отсрочки
Если вы считаете, что эта статья полезна для вас, добро пожаловатьСтавь лайк и оставляй сообщениеСкажи мне, что твоя поддержка является движущей силой для меня, чтобы продолжать творить, кстати, возможно, ты захочешь обратить внимание на мой личный публичный аккаунт."Технологическая станция «Снежная мечта»», регулярно обновляйте качественные статьи!