[{"data":1,"prerenderedAt":1367},["ShallowReactive",2],{"content-\u002F02-functions-errors\u002F02-defer":3},{"id":4,"title":5,"body":6,"description":12,"difficulty":1353,"extension":1354,"meta":1355,"module":1356,"navigation":165,"next":1357,"order":92,"path":1358,"prev":1359,"seo":1360,"slug":61,"stem":1361,"tags":1362,"__hash__":1366},"content\u002F02-functions-errors\u002F02-defer\u002Findex.md","Defer в Go",{"type":7,"value":8,"toc":1347},"minimark",[9,13,19,38,43,114,119,173,178,223,228,296,299,304,308,325,330,368,373,449,454,556,561,569,571,575,578,584,589,646,652,655,657,661,668,813,818,829,831,835,881,1051,1184,1341,1343],[10,11,12],"p",{},"defer -- откладывает вызов функции до выхода из текущей функции.",[10,14,15],{},[16,17,18],"strong",{},"Ключевые моменты:",[20,21,22,26,29,32,35],"ul",{},[23,24,25],"li",{},"выполняется при любом выходе (return, panic, конец функции)",[23,27,28],{},"LIFO порядок (последний defer -- первый выполнится)",[23,30,31],{},"аргументы вычисляются сразу, в момент defer",[23,33,34],{},"closure захватывает переменную, не значение",[23,36,37],{},"можно изменить named return через defer",[10,39,40],{},[16,41,42],{},"LIFO порядок:",[44,45,50],"pre",{"className":46,"code":47,"language":48,"meta":49,"style":49},"language-go shiki shiki-themes github-dark","defer fmt.Println(\"first\")\\ndefer fmt.Println(\"second\")\ndefer fmt.Println(\"third\")\\n\n\u002F\u002F third, second, first\n","go","",[51,52,53,90,107],"code",{"__ignoreMap":49},[54,55,58,62,66,70,73,77,80,82,84,87],"span",{"class":56,"line":57},"line",1,[54,59,61],{"class":60},"snl16","defer",[54,63,65],{"class":64},"s95oV"," fmt.",[54,67,69],{"class":68},"svObZ","Println",[54,71,72],{"class":64},"(",[54,74,76],{"class":75},"sU2Wk","\"first\"",[54,78,79],{"class":64},")\\ndefer fmt.",[54,81,69],{"class":68},[54,83,72],{"class":64},[54,85,86],{"class":75},"\"second\"",[54,88,89],{"class":64},")\n",[54,91,93,95,97,99,101,104],{"class":56,"line":92},2,[54,94,61],{"class":60},[54,96,65],{"class":64},[54,98,69],{"class":68},[54,100,72],{"class":64},[54,102,103],{"class":75},"\"third\"",[54,105,106],{"class":64},")\\n\n",[54,108,110],{"class":56,"line":109},3,[54,111,113],{"class":112},"sAwPA","\u002F\u002F third, second, first\n",[10,115,116],{},[16,117,118],{},"Аргументы вычисляются сразу:",[44,120,122],{"className":46,"code":121,"language":48,"meta":49,"style":49},"x := 10\ndefer fmt.Println(x)  \u002F\u002F вычисляется сейчас\nx = 20\n\n\u002F\u002F выведет 10\n",[51,123,124,136,150,160,167],{"__ignoreMap":49},[54,125,126,129,132],{"class":56,"line":57},[54,127,128],{"class":64},"x ",[54,130,131],{"class":60},":=",[54,133,135],{"class":134},"sDLfK"," 10\n",[54,137,138,140,142,144,147],{"class":56,"line":92},[54,139,61],{"class":60},[54,141,65],{"class":64},[54,143,69],{"class":68},[54,145,146],{"class":64},"(x)  ",[54,148,149],{"class":112},"\u002F\u002F вычисляется сейчас\n",[54,151,152,154,157],{"class":56,"line":109},[54,153,128],{"class":64},[54,155,156],{"class":60},"=",[54,158,159],{"class":134}," 20\n",[54,161,163],{"class":56,"line":162},4,[54,164,166],{"emptyLinePlaceholder":165},true,"\n",[54,168,170],{"class":56,"line":169},5,[54,171,172],{"class":112},"\u002F\u002F выведет 10\n",[10,174,175],{},[16,176,177],{},"Closure -- захватывает переменную:",[44,179,181],{"className":46,"code":180,"language":48,"meta":49,"style":49},"x := 10\ndefer func() { fmt.Println(x) }()\nx = 20\n\n\u002F\u002F выведет 20\n",[51,182,183,191,206,214,218],{"__ignoreMap":49},[54,184,185,187,189],{"class":56,"line":57},[54,186,128],{"class":64},[54,188,131],{"class":60},[54,190,135],{"class":134},[54,192,193,195,198,201,203],{"class":56,"line":92},[54,194,61],{"class":60},[54,196,197],{"class":60}," func",[54,199,200],{"class":64},"() { fmt.",[54,202,69],{"class":68},[54,204,205],{"class":64},"(x) }()\n",[54,207,208,210,212],{"class":56,"line":109},[54,209,128],{"class":64},[54,211,156],{"class":60},[54,213,159],{"class":134},[54,215,216],{"class":56,"line":162},[54,217,166],{"emptyLinePlaceholder":165},[54,219,220],{"class":56,"line":169},[54,221,222],{"class":112},"\u002F\u002F выведет 20\n",[10,224,225],{},[16,226,227],{},"Named return + defer:",[44,229,231],{"className":46,"code":230,"language":48,"meta":49,"style":49},"func double() (result int) {\n    result = 5\n    defer func() { result *= 2 }()\n    return  \u002F\u002F вернет 10\n}\n",[51,232,233,254,264,283,291],{"__ignoreMap":49},[54,234,235,238,241,244,248,251],{"class":56,"line":57},[54,236,237],{"class":60},"func",[54,239,240],{"class":68}," double",[54,242,243],{"class":64},"() (",[54,245,247],{"class":246},"s9osk","result",[54,249,250],{"class":60}," int",[54,252,253],{"class":64},") {\n",[54,255,256,259,261],{"class":56,"line":92},[54,257,258],{"class":64},"    result ",[54,260,156],{"class":60},[54,262,263],{"class":134}," 5\n",[54,265,266,269,271,274,277,280],{"class":56,"line":109},[54,267,268],{"class":60},"    defer",[54,270,197],{"class":60},[54,272,273],{"class":64},"() { result ",[54,275,276],{"class":60},"*=",[54,278,279],{"class":134}," 2",[54,281,282],{"class":64}," }()\n",[54,284,285,288],{"class":56,"line":162},[54,286,287],{"class":60},"    return",[54,289,290],{"class":112},"  \u002F\u002F вернет 10\n",[54,292,293],{"class":56,"line":169},[54,294,295],{"class":64},"}\n",[297,298],"hr",{},[300,301,303],"h2",{"id":302},"defer-и-panicrecover","Defer и panic\u002Frecover",[10,305,306],{},[16,307,18],{},[20,309,310,313,316,319,322],{},[23,311,312],{},"выполняется даже при panic",[23,314,315],{},"recover работает только внутри defer",[23,317,318],{},"defer в цикле копится до выхода из функции",[23,320,321],{},"до Go 1.14 был дорогой (~35ns), сейчас почти бесплатный (~5ns)",[23,323,324],{},"open-coded defer работает только для простых случаев (не в цикле)",[10,326,327],{},[16,328,329],{},"defer + panic:",[44,331,333],{"className":46,"code":332,"language":48,"meta":49,"style":49},"func risky() {\n    defer fmt.Println(\"cleanup\")  \u002F\u002F выполнится\\n    panic(\"oops\")\n}\n",[51,334,335,345,364],{"__ignoreMap":49},[54,336,337,339,342],{"class":56,"line":57},[54,338,237],{"class":60},[54,340,341],{"class":68}," risky",[54,343,344],{"class":64},"() {\n",[54,346,347,349,351,353,355,358,361],{"class":56,"line":92},[54,348,268],{"class":60},[54,350,65],{"class":64},[54,352,69],{"class":68},[54,354,72],{"class":64},[54,356,357],{"class":75},"\"cleanup\"",[54,359,360],{"class":64},")  ",[54,362,363],{"class":112},"\u002F\u002F выполнится\\n    panic(\"oops\")\n",[54,365,366],{"class":56,"line":109},[54,367,295],{"class":64},[10,369,370],{},[16,371,372],{},"panic + recover:",[44,374,376],{"className":46,"code":375,"language":48,"meta":49,"style":49},"defer func() {\n    if r := recover(); r != nil {\n        fmt.Println(\"recovered:\", r)\\n    }\n}()\npanic(\"oops\")\n\u002F\u002F программа продолжит работать\n",[51,377,378,386,411,426,431,443],{"__ignoreMap":49},[54,379,380,382,384],{"class":56,"line":57},[54,381,61],{"class":60},[54,383,197],{"class":60},[54,385,344],{"class":64},[54,387,388,391,394,396,399,402,405,408],{"class":56,"line":92},[54,389,390],{"class":60},"    if",[54,392,393],{"class":64}," r ",[54,395,131],{"class":60},[54,397,398],{"class":68}," recover",[54,400,401],{"class":64},"(); r ",[54,403,404],{"class":60},"!=",[54,406,407],{"class":134}," nil",[54,409,410],{"class":64}," {\n",[54,412,413,416,418,420,423],{"class":56,"line":109},[54,414,415],{"class":64},"        fmt.",[54,417,69],{"class":68},[54,419,72],{"class":64},[54,421,422],{"class":75},"\"recovered:\"",[54,424,425],{"class":64},", r)\\n    }\n",[54,427,428],{"class":56,"line":162},[54,429,430],{"class":64},"}()\n",[54,432,433,436,438,441],{"class":56,"line":169},[54,434,435],{"class":68},"panic",[54,437,72],{"class":64},[54,439,440],{"class":75},"\"oops\"",[54,442,89],{"class":64},[54,444,446],{"class":56,"line":445},6,[54,447,448],{"class":112},"\u002F\u002F программа продолжит работать\n",[10,450,451],{},[16,452,453],{},"Осторожно с циклом:",[44,455,457],{"className":46,"code":456,"language":48,"meta":49,"style":49},"for _, f := range files {\n    file, _ := os.Open(f)\n    defer file.Close()  \u002F\u002F копится до выхода из функции!\n}\n\u002F\u002F 1000 файлов = 1000 открытых хендлов\n\n\u002F\u002F решение: вынести в функцию\nfor _, f := range files {\n    processFile(f)  \u002F\u002F defer внутри закроется сразу\n}\n",[51,458,459,475,491,507,511,516,520,526,539,551],{"__ignoreMap":49},[54,460,461,464,467,469,472],{"class":56,"line":57},[54,462,463],{"class":60},"for",[54,465,466],{"class":64}," _, f ",[54,468,131],{"class":60},[54,470,471],{"class":60}," range",[54,473,474],{"class":64}," files {\n",[54,476,477,480,482,485,488],{"class":56,"line":92},[54,478,479],{"class":64},"    file, _ ",[54,481,131],{"class":60},[54,483,484],{"class":64}," os.",[54,486,487],{"class":68},"Open",[54,489,490],{"class":64},"(f)\n",[54,492,493,495,498,501,504],{"class":56,"line":109},[54,494,268],{"class":60},[54,496,497],{"class":64}," file.",[54,499,500],{"class":68},"Close",[54,502,503],{"class":64},"()  ",[54,505,506],{"class":112},"\u002F\u002F копится до выхода из функции!\n",[54,508,509],{"class":56,"line":162},[54,510,295],{"class":64},[54,512,513],{"class":56,"line":169},[54,514,515],{"class":112},"\u002F\u002F 1000 файлов = 1000 открытых хендлов\n",[54,517,518],{"class":56,"line":445},[54,519,166],{"emptyLinePlaceholder":165},[54,521,523],{"class":56,"line":522},7,[54,524,525],{"class":112},"\u002F\u002F решение: вынести в функцию\n",[54,527,529,531,533,535,537],{"class":56,"line":528},8,[54,530,463],{"class":60},[54,532,466],{"class":64},[54,534,131],{"class":60},[54,536,471],{"class":60},[54,538,474],{"class":64},[54,540,542,545,548],{"class":56,"line":541},9,[54,543,544],{"class":68},"    processFile",[54,546,547],{"class":64},"(f)  ",[54,549,550],{"class":112},"\u002F\u002F defer внутри закроется сразу\n",[54,552,554],{"class":56,"line":553},10,[54,555,295],{"class":64},[10,557,558],{},[16,559,560],{},"Производительность:",[44,562,567],{"className":563,"code":565,"language":566},[564],"language-text","до Go 1.14:  ~35 ns (дорого)\nGo 1.14+:    ~5 ns  (open-coded defer)\nобычный вызов: ~4 ns\n\nopen-coded работает если defer не в цикле\n","text",[51,568,565],{"__ignoreMap":49},[297,570],{},[300,572,574],{"id":573},"внутреннее-устройство-defer","Внутреннее устройство defer",[10,576,577],{},"Связный список в структуре G. Каждый defer добавляется в голову (поэтому LIFO).",[44,579,582],{"className":580,"code":581,"language":566},[564],"defer f1() → defer f2() → defer f3()\n\nG._defer → [f3] → [f2] → [f1] → nil\n            head              tail\n",[51,583,581],{"__ignoreMap":49},[10,585,586],{},[16,587,588],{},"Три реализации (эволюция):",[590,591,592,609],"table",{},[593,594,595],"thead",{},[596,597,598,603,606],"tr",{},[599,600,602],"th",{"align":601},"left","Версия",[599,604,605],{"align":601},"Способ",[599,607,608],{"align":601},"Скорость",[610,611,612,624,635],"tbody",{},[596,613,614,618,621],{},[615,616,617],"td",{"align":601},"\u003C Go 1.13",[615,619,620],{"align":601},"Heap-allocated defer record",[615,622,623],{"align":601},"~35 ns",[596,625,626,629,632],{},[615,627,628],{"align":601},"Go 1.13",[615,630,631],{"align":601},"Stack-allocated (если возможно)",[615,633,634],{"align":601},"~15 ns",[596,636,637,640,643],{},[615,638,639],{"align":601},"Go 1.14+",[615,641,642],{"align":601},"Open-coded defer",[615,644,645],{"align":601},"~5 ns",[10,647,648,651],{},[16,649,650],{},"Open-coded defer:"," компилятор инлайнит defer как обычный код в конце функции. Битовая маска отслеживает какие defer'ы были зарегистрированы. Нет аллокации, нет связного списка.",[10,653,654],{},"Работает только для простых случаев — не в цикле, не больше 8 defer'ов в функции. Иначе fallback на stack\u002Fheap.",[297,656],{},[300,658,660],{"id":659},"defer-и-mutex-подводные-камни","Defer и Mutex — подводные камни",[10,662,663,664,667],{},"defer выполняется при выходе из ",[16,665,666],{},"функции",", не из блока. Мьютекс держится дольше чем нужно:",[44,669,671],{"className":46,"code":670,"language":48,"meta":49,"style":49},"\u002F\u002F ❌ Мьютекс держится всю функцию\nfunc process() {\n    mu.Lock()\n    defer mu.Unlock()\n\n    data := readSharedData()  \u002F\u002F критическая секция — 1 строка\n    \n    \u002F\u002F ... 50 строк логики без shared data ...\n    \u002F\u002F всё это время мьютекс захвачен!\n}\n\n\u002F\u002F ✅ Отпускаем сразу после критической секции\nfunc process() {\n    mu.Lock()\n    data := readSharedData()\n    mu.Unlock()\n\n    \u002F\u002F ... 50 строк работают без блокировки\n}\n",[51,672,673,678,687,698,710,714,729,734,739,744,748,753,759,768,777,788,797,802,808],{"__ignoreMap":49},[54,674,675],{"class":56,"line":57},[54,676,677],{"class":112},"\u002F\u002F ❌ Мьютекс держится всю функцию\n",[54,679,680,682,685],{"class":56,"line":92},[54,681,237],{"class":60},[54,683,684],{"class":68}," process",[54,686,344],{"class":64},[54,688,689,692,695],{"class":56,"line":109},[54,690,691],{"class":64},"    mu.",[54,693,694],{"class":68},"Lock",[54,696,697],{"class":64},"()\n",[54,699,700,702,705,708],{"class":56,"line":162},[54,701,268],{"class":60},[54,703,704],{"class":64}," mu.",[54,706,707],{"class":68},"Unlock",[54,709,697],{"class":64},[54,711,712],{"class":56,"line":169},[54,713,166],{"emptyLinePlaceholder":165},[54,715,716,719,721,724,726],{"class":56,"line":445},[54,717,718],{"class":64},"    data ",[54,720,131],{"class":60},[54,722,723],{"class":68}," readSharedData",[54,725,503],{"class":64},[54,727,728],{"class":112},"\u002F\u002F критическая секция — 1 строка\n",[54,730,731],{"class":56,"line":522},[54,732,733],{"class":64},"    \n",[54,735,736],{"class":56,"line":528},[54,737,738],{"class":112},"    \u002F\u002F ... 50 строк логики без shared data ...\n",[54,740,741],{"class":56,"line":541},[54,742,743],{"class":112},"    \u002F\u002F всё это время мьютекс захвачен!\n",[54,745,746],{"class":56,"line":553},[54,747,295],{"class":64},[54,749,751],{"class":56,"line":750},11,[54,752,166],{"emptyLinePlaceholder":165},[54,754,756],{"class":56,"line":755},12,[54,757,758],{"class":112},"\u002F\u002F ✅ Отпускаем сразу после критической секции\n",[54,760,762,764,766],{"class":56,"line":761},13,[54,763,237],{"class":60},[54,765,684],{"class":68},[54,767,344],{"class":64},[54,769,771,773,775],{"class":56,"line":770},14,[54,772,691],{"class":64},[54,774,694],{"class":68},[54,776,697],{"class":64},[54,778,780,782,784,786],{"class":56,"line":779},15,[54,781,718],{"class":64},[54,783,131],{"class":60},[54,785,723],{"class":68},[54,787,697],{"class":64},[54,789,791,793,795],{"class":56,"line":790},16,[54,792,691],{"class":64},[54,794,707],{"class":68},[54,796,697],{"class":64},[54,798,800],{"class":56,"line":799},17,[54,801,166],{"emptyLinePlaceholder":165},[54,803,805],{"class":56,"line":804},18,[54,806,807],{"class":112},"    \u002F\u002F ... 50 строк работают без блокировки\n",[54,809,811],{"class":56,"line":810},19,[54,812,295],{"class":64},[10,814,815],{},[16,816,817],{},"Когда defer Unlock() нормально:",[20,819,820,823,826],{},[23,821,822],{},"Вся функция — критическая секция",[23,824,825],{},"Функция короткая (3-5 строк)",[23,827,828],{},"Много return\u002Fpanic — defer гарантирует Unlock",[297,830],{},[300,832,834],{"id":833},"практика","Практика",[836,837,841,847,864],"quiz",{"answer":838,"id":839,"xp":840},"3","funcs-defer-q1","10",[10,842,843,844,846],{},"В каком порядке выполняются несколько ",[51,845,61],{}," в одной функции?",[848,849,850],"template",{"v-slot:options":49},[20,851,852,855,858,861],{},[23,853,854],{},"В порядке объявления (первый объявленный — первый выполнится)",[23,856,857],{},"Одновременно, порядок не определён",[23,859,860],{},"В обратном порядке объявления (последний объявленный — первый выполнится)",[23,862,863],{},"Зависит от типа функции",[848,865,866],{"v-slot:explanation":49},[10,867,868,870,871,874,875,877,878,880],{},[51,869,61],{}," использует ",[16,872,873],{},"LIFO"," (Last In, First Out) — стек. Каждый ",[51,876,61],{}," добавляется в голову связного списка горутины. При выходе из функции список обходится от головы к хвосту, то есть последний зарегистрированный ",[51,879,61],{}," выполняется первым.",[882,883,887,890,1029],"predict",{"answer":884,"id":885,"xp":886},"start\\nthird\\nsecond\\nfirst\\nend","funcs-defer-p1","15",[10,888,889],{},"Угадай точный вывод программы.",[848,891,892],{"v-slot:code":49},[44,893,895],{"className":46,"code":894,"language":48,"meta":49,"style":49},"package main\n\nimport \"fmt\"\n\nfunc run() {\n    defer fmt.Println(\"first\")\\n    defer fmt.Println(\"second\")\n    defer fmt.Println(\"third\")\\n    fmt.Println(\"start\")\n}\n\nfunc main() {\n    run()\n    fmt.Println(\"end\")\n}\n",[51,896,897,905,909,923,927,936,963,987,991,995,1004,1011,1025],{"__ignoreMap":49},[54,898,899,902],{"class":56,"line":57},[54,900,901],{"class":60},"package",[54,903,904],{"class":68}," main\n",[54,906,907],{"class":56,"line":92},[54,908,166],{"emptyLinePlaceholder":165},[54,910,911,914,917,920],{"class":56,"line":109},[54,912,913],{"class":60},"import",[54,915,916],{"class":75}," \"",[54,918,919],{"class":68},"fmt",[54,921,922],{"class":75},"\"\n",[54,924,925],{"class":56,"line":162},[54,926,166],{"emptyLinePlaceholder":165},[54,928,929,931,934],{"class":56,"line":169},[54,930,237],{"class":60},[54,932,933],{"class":68}," run",[54,935,344],{"class":64},[54,937,938,940,942,944,946,948,951,953,955,957,959,961],{"class":56,"line":445},[54,939,268],{"class":60},[54,941,65],{"class":64},[54,943,69],{"class":68},[54,945,72],{"class":64},[54,947,76],{"class":75},[54,949,950],{"class":64},")\\n    ",[54,952,61],{"class":60},[54,954,65],{"class":64},[54,956,69],{"class":68},[54,958,72],{"class":64},[54,960,86],{"class":75},[54,962,89],{"class":64},[54,964,965,967,969,971,973,975,978,980,982,985],{"class":56,"line":522},[54,966,268],{"class":60},[54,968,65],{"class":64},[54,970,69],{"class":68},[54,972,72],{"class":64},[54,974,103],{"class":75},[54,976,977],{"class":64},")\\n    fmt.",[54,979,69],{"class":68},[54,981,72],{"class":64},[54,983,984],{"class":75},"\"start\"",[54,986,89],{"class":64},[54,988,989],{"class":56,"line":528},[54,990,295],{"class":64},[54,992,993],{"class":56,"line":541},[54,994,166],{"emptyLinePlaceholder":165},[54,996,997,999,1002],{"class":56,"line":553},[54,998,237],{"class":60},[54,1000,1001],{"class":68}," main",[54,1003,344],{"class":64},[54,1005,1006,1009],{"class":56,"line":750},[54,1007,1008],{"class":68},"    run",[54,1010,697],{"class":64},[54,1012,1013,1016,1018,1020,1023],{"class":56,"line":755},[54,1014,1015],{"class":64},"    fmt.",[54,1017,69],{"class":68},[54,1019,72],{"class":64},[54,1021,1022],{"class":75},"\"end\"",[54,1024,89],{"class":64},[54,1026,1027],{"class":56,"line":761},[54,1028,295],{"class":64},[848,1030,1031],{"v-slot:hint":49},[10,1032,1033,1036,1037,1039,1040,1043,1044,1046,1047,1050],{},[51,1034,1035],{},"fmt.Println(\"start\")"," выполняется сразу. Три ",[51,1038,61],{}," выполняются при выходе из ",[51,1041,1042],{},"run()"," в порядке LIFO. После возврата из ",[51,1045,1042],{}," выполняется ",[51,1048,1049],{},"fmt.Println(\"end\")",".",[882,1052,1054,1061,1167],{"answer":840,"id":1053,"xp":886},"funcs-defer-p2",[10,1055,1056,1057,1060],{},"Что выведет функция ",[51,1058,1059],{},"double()","?",[848,1062,1063],{"v-slot:code":49},[44,1064,1066],{"className":46,"code":1065,"language":48,"meta":49,"style":49},"package main\n\nimport \"fmt\"\n\nfunc double() (result int) {\n    result = 5\n    defer func() { result *= 2 }()\n    return\n}\n\nfunc main() {\n    fmt.Println(double())\n}\n",[51,1067,1068,1074,1078,1088,1092,1106,1114,1128,1133,1137,1141,1149,1163],{"__ignoreMap":49},[54,1069,1070,1072],{"class":56,"line":57},[54,1071,901],{"class":60},[54,1073,904],{"class":68},[54,1075,1076],{"class":56,"line":92},[54,1077,166],{"emptyLinePlaceholder":165},[54,1079,1080,1082,1084,1086],{"class":56,"line":109},[54,1081,913],{"class":60},[54,1083,916],{"class":75},[54,1085,919],{"class":68},[54,1087,922],{"class":75},[54,1089,1090],{"class":56,"line":162},[54,1091,166],{"emptyLinePlaceholder":165},[54,1093,1094,1096,1098,1100,1102,1104],{"class":56,"line":169},[54,1095,237],{"class":60},[54,1097,240],{"class":68},[54,1099,243],{"class":64},[54,1101,247],{"class":246},[54,1103,250],{"class":60},[54,1105,253],{"class":64},[54,1107,1108,1110,1112],{"class":56,"line":445},[54,1109,258],{"class":64},[54,1111,156],{"class":60},[54,1113,263],{"class":134},[54,1115,1116,1118,1120,1122,1124,1126],{"class":56,"line":522},[54,1117,268],{"class":60},[54,1119,197],{"class":60},[54,1121,273],{"class":64},[54,1123,276],{"class":60},[54,1125,279],{"class":134},[54,1127,282],{"class":64},[54,1129,1130],{"class":56,"line":528},[54,1131,1132],{"class":60},"    return\n",[54,1134,1135],{"class":56,"line":541},[54,1136,295],{"class":64},[54,1138,1139],{"class":56,"line":553},[54,1140,166],{"emptyLinePlaceholder":165},[54,1142,1143,1145,1147],{"class":56,"line":750},[54,1144,237],{"class":60},[54,1146,1001],{"class":68},[54,1148,344],{"class":64},[54,1150,1151,1153,1155,1157,1160],{"class":56,"line":755},[54,1152,1015],{"class":64},[54,1154,69],{"class":68},[54,1156,72],{"class":64},[54,1158,1159],{"class":68},"double",[54,1161,1162],{"class":64},"())\n",[54,1164,1165],{"class":56,"line":761},[54,1166,295],{"class":64},[848,1168,1169],{"v-slot:hint":49},[10,1170,1171,1174,1175,1177,1178,1180,1181,1183],{},[51,1172,1173],{},"return"," в функции с именованным возвращаемым значением сначала записывает значение в ",[51,1176,247],{},", потом выполняет ",[51,1179,61],{},", потом возвращает. Defer может изменить ",[51,1182,247],{}," — именно это здесь и происходит.",[1185,1186,1190,1195,1317],"code-fix",{"expected":1187,"id":1188,"xp":1189},"opening file\\nclosing file\\ndone","funcs-defer-cf1","25",[10,1191,1192,1193,1050],{},"Исправь код: файл должен закрываться всегда, даже если возникнет ошибка позже в функции. Используй ",[51,1194,61],{},[848,1196,1197],{"v-slot:code":49},[44,1198,1200],{"className":46,"code":1199,"language":48,"meta":49,"style":49},"package main\n\nimport \"fmt\"\n\nfunc processFile() {\n    fmt.Println(\"opening file\")\\n    \u002F\u002F представим что здесь открываем файл\n\n    \u002F\u002F много логики...\n    fmt.Println(\"done\")\\n\n    \u002F\u002F закрытие файла — только в конце, но что если паника выше?\n    fmt.Println(\"closing file\")\n}\n\nfunc main() {\n    processFile()\n}\n",[51,1201,1202,1208,1212,1222,1226,1235,1251,1255,1260,1273,1278,1291,1295,1299,1307,1313],{"__ignoreMap":49},[54,1203,1204,1206],{"class":56,"line":57},[54,1205,901],{"class":60},[54,1207,904],{"class":68},[54,1209,1210],{"class":56,"line":92},[54,1211,166],{"emptyLinePlaceholder":165},[54,1213,1214,1216,1218,1220],{"class":56,"line":109},[54,1215,913],{"class":60},[54,1217,916],{"class":75},[54,1219,919],{"class":68},[54,1221,922],{"class":75},[54,1223,1224],{"class":56,"line":162},[54,1225,166],{"emptyLinePlaceholder":165},[54,1227,1228,1230,1233],{"class":56,"line":169},[54,1229,237],{"class":60},[54,1231,1232],{"class":68}," processFile",[54,1234,344],{"class":64},[54,1236,1237,1239,1241,1243,1246,1248],{"class":56,"line":445},[54,1238,1015],{"class":64},[54,1240,69],{"class":68},[54,1242,72],{"class":64},[54,1244,1245],{"class":75},"\"opening file\"",[54,1247,950],{"class":64},[54,1249,1250],{"class":112},"\u002F\u002F представим что здесь открываем файл\n",[54,1252,1253],{"class":56,"line":522},[54,1254,166],{"emptyLinePlaceholder":165},[54,1256,1257],{"class":56,"line":528},[54,1258,1259],{"class":112},"    \u002F\u002F много логики...\n",[54,1261,1262,1264,1266,1268,1271],{"class":56,"line":541},[54,1263,1015],{"class":64},[54,1265,69],{"class":68},[54,1267,72],{"class":64},[54,1269,1270],{"class":75},"\"done\"",[54,1272,106],{"class":64},[54,1274,1275],{"class":56,"line":553},[54,1276,1277],{"class":112},"    \u002F\u002F закрытие файла — только в конце, но что если паника выше?\n",[54,1279,1280,1282,1284,1286,1289],{"class":56,"line":750},[54,1281,1015],{"class":64},[54,1283,69],{"class":68},[54,1285,72],{"class":64},[54,1287,1288],{"class":75},"\"closing file\"",[54,1290,89],{"class":64},[54,1292,1293],{"class":56,"line":755},[54,1294,295],{"class":64},[54,1296,1297],{"class":56,"line":761},[54,1298,166],{"emptyLinePlaceholder":165},[54,1300,1301,1303,1305],{"class":56,"line":770},[54,1302,237],{"class":60},[54,1304,1001],{"class":68},[54,1306,344],{"class":64},[54,1308,1309,1311],{"class":56,"line":779},[54,1310,544],{"class":68},[54,1312,697],{"class":64},[54,1314,1315],{"class":56,"line":790},[54,1316,295],{"class":64},[848,1318,1319],{"v-slot:hints":49},[20,1320,1321,1331],{},[23,1322,1323,1324,1327,1328],{},"Переставь ",[51,1325,1326],{},"fmt.Println(\"closing file\")"," сразу после \"opening file\", но обернув в ",[51,1329,1330],{},"defer func() { ... }()",[23,1332,1333,1335,1336,1338,1339],{},[51,1334,61],{}," гарантирует выполнение при любом выходе из функции — и при ",[51,1337,1173],{},", и при ",[51,1340,435],{},[297,1342],{},[1344,1345,1346],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":49,"searchDepth":92,"depth":92,"links":1348},[1349,1350,1351,1352],{"id":302,"depth":92,"text":303},{"id":573,"depth":92,"text":574},{"id":659,"depth":92,"text":660},{"id":833,"depth":92,"text":834},"beginner","md",{},"functions-errors","errors","\u002F02-functions-errors\u002F02-defer","functions",{"title":5,"description":12},"02-functions-errors\u002F02-defer\u002Findex",[61,873,435,1363,1364,1365],"recover","named return","open-coded defer","7SOix_Yx4XJ4EPytR438E3PcWdJfgXUmrVSP8Asoscg",1776289836585]