मुख्य सामग्री पर जाएं
मॉड्यूल 3 · पाठ 5 का 5पाठ्यक्रम में 15/50~12 min
मॉड्यूल पाठ (5/5)

`स्थगित`: गारंटीकृत सफ़ाई

defer कॉल के निष्पादन को एनक्लोजिंग फ़ंक्शन तक स्थगित कर देता है रिटर्न. यह तब भी चलता है जब फ़ंक्शन घबराहट के कारण बाहर निकल जाता है। एकाधिक defers उसी फ़ंक्शन में LIFO क्रम (लास्ट-इन, फ़र्स्ट-आउट) में निष्पादित करें।

यह संसाधन सफाई के लिए मुहावरेदार तंत्र है: फ़ाइलें बंद करना, म्यूटेक्स को अनलॉक करना, कनेक्शन जारी करना, स्थिति बहाल करना।

सिंटैक्स और कैनोनिकल उपयोग का मामला

Go
f, err := os.Open(path)
if err != nil {
    return err
}
defer f.Close()   // chiamata SEMPRE all'uscita della funzione

// ... usa f liberamente ...
return nil

विशिष्ट: f.Close(), mu.Unlock(), db.Close(), tx.Rollback(), recover().

तर्कों का तुरंत मूल्यांकन किया गया, निष्पादन स्थगित कर दिया गया

जब आप defer foo(x) लिखते हैं, तो x का मूल्यांकन उस समय किया जाता है defer, निष्पादन समय पर नहीं:

Go
x := 10
defer fmt.Println(x)   // cattura 10
x = 99
// quando la funzione ritorna stampa "10", non "99"

लाइफ़ो आदेश

डिफर्स ढेर हो जाते हैं और सबसे हाल से शुरू करके निष्पादित होते हैं:

Go
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
// output: 3, 2, 1

यह संसाधन शब्दार्थ के अनुरूप है: अंतिम खोला गया पहला है बंद किया जाना.

defer + recover: घबराहट से निपटना

defer panic को रोकने का एकमात्र तरीका है:

Go
func safe() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("recuperato:", r)
        }
    }()
    panic("boom")
}

ख़तरा: defer एक लूप में

defer f.Close() को लूप में डालने से ** के अंत तक विलंब जमा हो जाता है फ़ंक्शन**, प्रत्येक पुनरावृत्ति का नहीं। एक लंबे लूप में आप कई फ़ाइलें खोलते हैं और फ़ंक्शन बंद होने पर ही उन्हें बंद करें: फ़ाइल डिस्क्रिप्टर लीक का जोखिम।

Go
// MALE: defer accumulati
for _, path := range paths {
    f, _ := os.Open(path)
    defer f.Close()   // chiude TUTTI alla fine della funzione esterna
    // ...
}

// MEGLIO: estrai in una funzione
for _, path := range paths {
    elabora(path)   // ogni chiamata ha il proprio scope di defer
}

इसे अजमाएं

व्यायाम#go.m3.l5.e1
प्रयास: 0लोड हो रहा है...

'इनिज़ियो' प्रिंट करें, फिर 'फाइन' का प्रिंट डेफ़र के साथ प्रिंट करें, फिर 'मेज़ो' प्रिंट करें। आउटपुट होना चाहिए: इनिज़ियो / मेज़ो / फाइन।

संपादक लोड हो रहा है...
संकेत दिखाएँ

डिफ़र तब चलता है जब मुख्य() वापस लौटने वाला होता है।

3 प्रयासों के बाद समाधान उपलब्ध है

व्यायाम#go.m3.l5.e2
प्रयास: 0लोड हो रहा है...

कोड में उस क्रम में 1, 2 और 3 प्रिंट करने वाले लगातार तीन डिफर्स लिखें। आउटपुट 3/2/1 (LIFO) होगा।

संपादक लोड हो रहा है...
संकेत दिखाएँ

क्रम में तीन विलंब; याद रखें कि वे उल्टे क्रम में निष्पादित होते हैं।

3 प्रयासों के बाद समाधान उपलब्ध है

Quiz#go.m3.l5.e3
तैयार

यह क्या छापता है? (नोट: स्थगित तर्कों का तुरंत मूल्यांकन किया जाता है)

Go
x := 10
defer fmt.Println(x)
x = 99
उत्तर विकल्प

संक्षिप्त

  • defer call() फ़ंक्शन वापस आने तक निष्पादन स्थगित कर देता है।
  • एकाधिक स्थगन = LIFO आदेश।
  • तर्कों का तुरंत मूल्यांकन किया गया, निष्पादन स्थगित कर दिया गया।
  • नियतात्मक सफाई के लिए उपयोग किया जाता है: फ़ाइलें, म्यूटेक्स, कनेक्शन।
  • defer + recover() एक panic को रोकता है (दुर्लभ, सीमाओं पर)।
  • लंबे लूप के अंदर कभी भी defer न करें: यह बाहरी फ़ंक्शन के वापस आने तक जमा होता रहता है।