Go में init() कब काम करता है? उदाहरणों के साथ विश्लेषण

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

Go में init() कब चलता है? वास्तविक उदाहरण के साथ समझें

\n\n

कल्पना करें: आप Go में एक माइक्रोसर्विस लिख रहे हैं। एक पैकेज में आपने कॉन्फ़िग लोड करने के लिए init() घोषित किया। आप एप्लिकेशन चलाते हैं — और अचानक यह nil pointer dereference के साथ क्रैश हो जाता है। आप घबरा जाते हैं: "क्यों? कॉन्फ़िग तो पहले लोड होना चाहिए था!"

\n\n

परिचित लगता है? यदि हाँ, तो आप अकेले नहीं हैं। सवाल "init() फ़ंक्शन कब चलता है?" Stack Overflow पर सबसे लोकप्रिय प्रश्नों में से एक है (हज़ारों व्यूज़)। आइए एक बार और हमेशा के लिए समझ लें कि Go में init() कब और किस क्रम में काम करता है, ताकि आप इस जाल में फिर से न फँसें।

\n\n

init() क्या है और इसकी आवश्यकता क्यों है?

\n\n

Go में init() एक विशेष फ़ंक्शन है जिसमें कोई पैरामीटर और रिटर्न वैल्यू नहीं होती। इसे स्पष्ट रूप से कॉल नहीं किया जाता। इसे Go रनटाइम main() फ़ंक्शन के निष्पादन से पहले स्वचालित रूप से चलाता है।

\n\n

इसकी आवश्यकता क्यों है?

\n\n
    \n
  • ग्लोबल वेरिएबल्स को आरंभ करना जिनमें जटिल लॉजिक की आवश्यकता होती है (जैसे फ़ाइल से पढ़ना)।
  • \n
  • डेटाबेस ड्राइवरों या HTTP हैंडलर को रजिस्टर करना।
  • \n
  • एनवायरनमेंट की जाँच करना (एनवायरनमेंट वेरिएबल्स, संसाधनों की उपलब्धता)।
  • \n
\n\n

लेकिन मुख्य नियम: आपको कभी भी एक ही पैकेज की अलग-अलग फ़ाइलों के बीच init() के निष्पादन क्रम पर भरोसा नहीं करना चाहिए। और यहाँ कारण है।

\n\n

init() वास्तव में कब चलता है? सटीक क्रम

\n\n

Go init() को सख्त नियमों के अनुसार निष्पादित करता है। आइए इसे चरणों में समझते हैं।

\n\n

नियम #1: एक पैकेज — एक क्रम

\n

एक ही पैकेज के अंदर, init() फ़ाइलों के घोषणा क्रम में निष्पादित होता है (फ़ाइल नामों के वर्णमाला क्रम में)। लेकिन यह कार्यान्वयन विवरण है — इस पर भरोसा न करना बेहतर है।

\n\n

नियम #2: पहले वेरिएबल आरंभीकरण, फिर init()

\n

init() को कॉल करने से पहले, Go पैकेज में सभी ग्लोबल वेरिएबल्स को आरंभ करता है। यदि कोई वेरिएबल उसी पैकेज के किसी अन्य वेरिएबल पर निर्भर करता है — तो उनके घोषणा क्रम का महत्व है।

\n\n
package config\n\nvar AppName string = "MyApp"\nvar Version string = getVersion() // init() से पहले कॉल होगा\n\nfunc init() {\n    // यहाँ AppName और Version पहले से उपलब्ध हैं\n    println("Init started for", AppName)\n}\n\nfunc getVersion() string {\n    return "1.0.0"\n}
\n\n

नियम #3: आयातित पैकेज पहले आरंभ होते हैं

\n

यह सबसे महत्वपूर्ण नियम है। यदि पैकेज A, पैकेज B को आयात करता है, तो पहले पैकेज B में सभी init() निष्पादित होंगे, और उसके बाद ही A में। Go निर्भरता ग्राफ बनाता है और "नीचे से ऊपर" आरंभीकरण करता है।

\n\n
// पैकेज database\npackage database\n\nfunc init() {\n    println("1. database init")\n}\n\n// पैकेज main (database आयात करता है)\npackage main\n\nimport "myapp/database"\n\nfunc init() {\n    println("2. main init")\n}\n\nfunc main() {\n    println("3. main function")\n}\n\n// आउटपुट:\n// 1. database init\n// 2. main init\n// 3. main function
\n\n

नियम #4: एक फ़ाइल में कई init() — संभव है, लेकिन आवश्यक नहीं

\n

एक फ़ाइल में कई init() हो सकते हैं। वे घोषणा क्रम में निष्पादित होंगे। लेकिन इससे कोड पढ़ना मुश्किल हो जाता है। बेहतर है कि लॉजिक को एक फ़ंक्शन में संयोजित करें।

\n\n

वास्तविक उदाहरण: यदि क्रम में गलती हो जाए तो क्या होगा?

\n\n

आइए एक शुरुआती की सामान्य गलती का अनुकरण करें। मान लें कि हमारे पास एक पैकेज config है जो फ़ाइल से सेटिंग्स पढ़ता है, और एक पैकेज app है जो इन सेटिंग्स का उपयोग करता है।

\n\n
// config.go\npackage config\n\nvar Settings map[string]string\n\nfunc init() {\n    // फ़ाइल पढ़ने का अनुकरण\n    Settings = map[string]string{\n        "port": "8080",\n        "host": "localhost",\n    }\n    println("Config loaded")\n}\n\n// app.go\npackage app\n\nimport "myapp/config"\n\nvar ServerPort string\n\nfunc init() {\n    // त्रुटि: यदि config.Settings अभी तक आरंभ नहीं हुआ है                

ब्लॉग

पुस्तक अनुशंसाएँ