1 जीको में defer फीचर का परिचय

गो भाषा में, defer बयान को यहाँ तक करता है कि इसके बाद आने वाली फ़ंक्शन कॉल को वो तब तक विलंबित करता है जब तक defer बयान को धारक फ़ंक्शन को पूरा करने के लिए बचेगा। हम इसे अन्य प्रोग्रामिंग भाषाओं की finally ब्लॉक की तरह सोच सकते हैं, लेकिन defer का उपयोग और भी लचीला और अनूठा है।

defer का उपयोग करने का लाभ यह है कि इसका उपयोग फाइलें बंद करना, म्यूटेक्स अनलॉक करना, या बस फ़ंक्शन के बाहर निकलने का समय दर्ज करना जैसे सफ़ाई के कामों को करने के लिए किया जा सकता है। इससे प्रोग्राम को मजबूत बनाया जा सकता है और अपशिष्ट प्रबंधन में प्रोग्रामिंग काम की मात्रा को कम किया जा सकता है। गो के डिज़ाइन दर्शन के अनुसार, defer का उपयोग करना सिफ़र संरचित और पठनीय है, जो त्रुटियों, संसाधन सफाई और अन्य अनुसूची क्रियाओं को संभालते समय कोड को रखने में मदद करता है।

2 defer का कार्य सिद्धांत

2.1 मूल कार्य सिद्धांत

defer का मूल काम सिद्धांत है कि एक स्टैक (लास्ट इन, फर्स्ट आउट सिद्धांत) का उपयोग करना, जिसमें प्रत्येक विलंबित फ़ंक्शन को संग्रहित किया जाता है जो कार्यान्वयन के लिए होने वाला है। जब एक defer बयान प्रकट होता है, तो गो भाषा सीधे ही बयान के बाद आने वाले फ़ंक्शन को क्रियान्वित नहीं करती है। बल्कि, यह उसे एक विशेष स्टैक में ढकेलती है। केवल जब बाह्य फ़ंक्शन वापस जाने वाला होता है, तब ये विलंबित फ़ंक्शन स्टैक के क्रम में क्रियान्वित होते हैं, जिसमें उन्हें पिछले घोषित defer ब्यान के स्थान के क्रम में क्रियान्वित किया जाता है।

इसके अलावा, इसका महत्वपूर्ण बात ध्यान देने योग्य है कि defer बयान के बाद आने वाले फ़ंक्शन में पैरामीटर वास्तविक किए गए और ठोस किए गए होते हैं, बल्कि वास्तविक क्रियान्वयन के समय नहीं।

func example() {
    defer fmt.Println("दुनिया") // विलंबित हो गया
    fmt.Println("नमस्ते")
}

func main() {
    example()
}

ऊपर का कोड निम्नलिखित आउटपुट देगा:

नमस्ते
दुनिया

दुनिया को कोड में नमस्ते से पहले प्रिंट किया जाएगा, भले ही कि वह कोड में पहले आ रहा हो।

2.2 विभिन्न defer बयानों के निष्पादन का क्रम

जब किसी फ़ंक्शन में कई defer बयान होते हैं, तो वे लास्ट इन, फर्स्ट आउट क्रम में निष्पादित होते हैं। इसलिए समझदारी के लिए यह अक्सर बहुत महत्वपूर्ण होता है। निम्नलिखित उदाहरण में दिखाया गया है कि कई defer बयानों के निष्पादन का क्रम कैसा होता है:

func multipleDefers() {
    defer fmt.Println("पहला विलंबित")
    defer fmt.Println("दूसरा विलंबित")
    defer fmt.Println("तीसरा विलंबित")

    fmt.Println("फ़ंक्शन बॉडी")
}

func main() {
    multipleDefers()
}

इस कोड का आउटपुट होगा:

फ़ंक्शन बॉडी
तीसरा विलंबित
दूसरा विलंबित
पहला विलंबित

defer लास्ट इन, फर्स्ट आउट सिद्धांत का पालन करता है, इसलिए भले ही "पहला विलंबित" सबसे पहले था, लेकिन यह अंत में ही निष्पादित होगा।

3 विभिन्न परिदृश्यों में defer का अनुप्रयोग

3.1 संसाधन विमुक्ति

गो भाषा में, defer बयान का उपयोग संसाधन विमुक्ति तर्कों को संभालने के लिए किया जाता है, जैसे फ़ाइल कार्यों और डेटाबेस कनेक्शन। defer यह सुनिश्चित करता है कि फ़ंक्शन का निष्क्रिय होने के बाद, संबंधित संसाधन सही रूप से रिलीज़ हो जाएंगे, चाहे फ़ंक्शन को छोड़ने का कारण कुछ भी हो।

फ़ाइल कार्यन

func ReadFile(filename string) {
    file, err := os.Open(filename)
    if err != nil {
        log.Fatal(err)
    }
    // फ़ाइल बंद करने को सुनिश्चित करने के लिए डिफर का उपयोग करें
    defer file.Close()

    // फ़ाइल पठन के कार्य...
}

इस उदाहरण में, एक बार os.Open सफलतापूर्वक फ़ाइल खोलता है, तो उसके बाद का defer file.Close() बयान सुनिश्चित करता है कि फ़ंक्शन समाप्त होने पर फ़ाइल संसाधन सही रूप से बंद होगा और फ़ाइल हैंडल संसाधन रिलीज़ हो जाएगा।

डेटाबेस कनेक्शन उदाहरण

func QueryDatabase(query string) {
    db, err := sql.Open("mysql", "user:password@/dbname")
    if err != nil {
        log.Fatal(err)
    }
    // डिफर का उपयोग करके सुनिश्चित करें कि डेटाबेस कनेक्शन बंद हो
    defer db.Close()

    // डेटाबेस क्वेरी कार्यों...
}

इसी तरह, defer db.Close() सुनिश्चित करता है कि QueryDatabase फ़ंक्शन छोड़ते समय डेटाबेस कनेक्शन बंद हो जाएगा, चाहे कारण (सामान्य रिटर्न या अनूचितता फेंक दी गई) कुछ भी हो।

3.2 समवर्ती प्रोग्रामिंग में ताले की कार्यवाही

समवर्ती प्रोग्रामिंग में, म्यूटेक्स ताले की रिहाई को संभालने के लिए defer का उपयोग करना एक अच्छा अभ्यास है। इससे यह सुनिश्चित होता है कि क्रिटिकल सेक्शन कोड कार्यान्वित होने के बाद लॉक सही ढंग से रिहा किया जाता है, असंजय स्थितियों से बचाव करते हुए।

Mutex Lock उदाहरण:

var mutex sync.Mutex

func updateSharedResource() {
    mutex.Lock()
    // Lock को रिलीज़ करने की सुनिश्चिति के लिए defer का उपयोग करें
    defer mutex.Unlock()

    // साझा संसाधन में संशोधन करें...
}

साझा संसाधन के संशोधन सफल हो या किसी दुर्घटना का वारण हो, defer सुनिश्चित करेगा कि Unlock() को कॉल किया जाए, जिससे दूसरी गोरूटीनें जो लॉक की प्रतीक्षा कर रही हैं, उसे प्राप्त कर सकें।

सुझाव: म्यूटेक्स लॉक के विस्तृत विवरण आने वाले अध्यायों में शामिल किए जाएंगे। इस समय defer के अनुप्रयोग के अनुप्रयुक्ति को समझना पर्याप्त है।

defer के लिए 3 सामान्य खतरे और विचारकों का ध्यान रखें

defer का उपयोग करते समय, हालात की सुविधा और रखरखाव में सुधार होता है, लेकिन इसमें कुछ खतरे और विचारकों का भी ध्यान रखना चाहिए।

3.1 स्वतंत्र संवेदनशीलता फ़ंक्शन पैरामीटर तुरंत मूल्यांकन होते हैं

func printValue(v int) {
    fmt.Println("मूल्य:", v)
}

func main() {
    value := 1
    defer printValue(value)
    // `defer` में पहले से ही पारित पैरामीटर परिभाषित हो जाने की वजह से `मूल्य` के मूल्य के परिवर्तन का कोई असर नहीं होगा
    value = 2
}
// आउटपुट "मूल्य: 1" होगा

defer के वक्त, मूल्य के मूल्य के परिवर्तन के बावजूद, defer में printValue को पास करने का पैरामीटर पहले से ही मूल्यांकित और निश्चित हो जाता है, इसलिए आउटपुट फिर भी "मूल्य: 1" होगा।

3.2 ध्यान रखें जब लूप के भीतर defer का उपयोग करते समय

लूप के भीतर defer का उपयोग, संसाधनों को लूप समाप्त होने से पहले रिलीज़ नहीं होने की और ले जा सकता है, जो संसाधनों के इस्तेमाल या उसकी कमी का कारण बन सकता है।

3.3 साथ प्रोग्रामिंग में "उपयोग के बाद रिलीज़" से बचें

साथ प्रोग्रामों में, संसाधनों को रिलीज़ करने के लिए defer का उपयोग करते समय, यह महत्वपूर्ण है कि सुनिश्चित किया जाए कि सभी गोरूटीनें संसाधन का उपयोग करने का प्रयास न करें, जिससे रेस की स्थिति से बचा जा सके।

4. defer बयानों की क्रियान्वयन क्रम का ध्यान रखें

defer बयानों म