Go में Import cycle not allowed: दुष्चक्र को कैसे तोड़ें

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

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

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

Import cycle not allowed: जब Go कोड के रास्ते में रोड़ा अटकाता है

\n\n

प्रत्येक Go-डेवलपर को देर-सबेर इस वाक्यांश का सामना करना पड़ता है। कंपाइलर अचानक बिल्ड को रोक देता है, एक सूखा संदेश देता है: import cycle not allowed। ऐसा लगता है कि प्रोग्राम तार्किक है, और पैकेज "जैसा चाहिए" जुड़े हुए हैं। लेकिन Go अलग सोचता है।

\n\n

यह त्रुटि भाषा की सनक नहीं है, बल्कि अराजकता से सुरक्षा है। चक्रीय निर्भरताएँ कोड को उलझा देती हैं, परीक्षण को जटिल बनाती हैं और बिल्ड को अप्रत्याशित बना देती हैं। इस लेख में, हम समझेंगे कि import cycle not allowed क्यों होता है, और इसे खत्म करने के तीन दृष्टिकोणों की तुलना करेंगे: इंटरफ़ेस के माध्यम से, मध्यस्थ पैकेज के माध्यम से और रीफैक्टरिंग के माध्यम से। आप जानेंगे कि स्थिति के अनुसार कौन सी विधि चुननी है।

\n\n

Go चक्रीय आयात पर प्रतिबंध क्यों लगाता है?

\n\n

डायनामिक लोडिंग वाली भाषाओं (Python, JavaScript) के विपरीत, Go स्थिर रूप से संकलित होता है। कंपाइलर एक बार पैकेजों का निर्भरता ग्राफ बनाता है। यदि पैकेज A, पैकेज B को आयात करता है, और B, A को आयात करता है - तो एक चक्र बनता है। Go इस क्रम को हल नहीं कर सकता, इसलिए संकलन रोक देता है।

\n\n

जीवन का एक उदाहरण: पैकेज users उपयोगकर्ताओं के साथ काम करता है, पैकेज orders ऑर्डर के साथ। orders में उपयोगकर्ता की जानकारी चाहिए, और users में ऑर्डर की सूची। परिणाम: import cycle not allowed।

\n\n

विशिष्ट परिदृश्य: दो पैकेज जो बहुत करीबी "दोस्त" हैं

\n\n

एक क्लासिक स्थिति पर विचार करें। हमारे पास दो पैकेज हैं: users और notifier।

\n\n

पैकेज users (फ़ाइल users.go):

\n
package users\n\nimport "notifier"\n\ntype User struct {\n    Name  string\n    Email string\n}\n\nfunc (u *User) SendWelcome() {\n    notifier.Notify(u.Email, "Welcome!")\n}\n
\n\n

पैकेज notifier (फ़ाइल notifier.go):

\n
package notifier\n\nimport "users"\n\nfunc Notify(email, msg string) {\n    // सूचना भेजें\n}\n\nfunc GetUserEmail(user *users.User) string {\n    return user.Email\n}\n
\n\n

कंपाइलर देगा: import cycle not allowed: users -> notifier -> users। दोनों पैकेज एक-दूसरे को आयात करने का प्रयास कर रहे हैं। क्या करें?

\n\n

दृष्टिकोण 1: इंटरफ़ेस — "बाँटो और राज करो"

\n\n

सबसे सुंदर तरीका निर्भरता को इंटरफ़ेस स्तर पर ले जाना है। Go स्पष्ट अनुबंध पसंद करता है।

\n\n

हम पैकेज contracts बनाते हैं, जहाँ हम इंटरफ़ेस Notifier परिभाषित करते हैं:

\n
// contracts/contracts.go\npackage contracts\n\ntype Notifier interface {\n    Notify(email, msg string)\n}\n
\n\n

अब users सीधे notifier पर निर्भर नहीं है:

\n
// users/users.go\npackage users\n\nimport "contracts"\n\ntype User struct {\n    Name  string\n    Email string\n}\n\nfunc (u *User) SendWelcome(n contracts.Notifier) {\n    n.Notify(u.Email, "Welcome!")\n}\n
\n\n

और notifier इंटरफ़ेस को लागू करता है:

\n
// notifier/notifier.go\npackage notifier\n\ntype EmailNotifier struct{}\n\nfunc (e *EmailNotifier) Notify(email, msg string) {\n    // भेजने का तर्क\n}\n
\n\n

लाभ:

\n
    \n
  • चक्रीय आयात का पूर्ण अभाव।
  • \n
  • आसान परीक्षण: कार्यान्वयन को बदला जा सकता है।
  • \n
  • ढीला युग्मन (loose coupling)।
  • \n
\n

नुकसान:

\n
    \n
  • इंटरफ़ेस वाले अतिरिक्त पैकेज की आवश्यकता।
  • \n
  • कभी-कभी सरल प्रोजेक्ट के लिए इंटरफ़ेस आवश्यक नहीं होते।
  • \n
\n\n

दृष्टिकोण 2: मध्यस्थ पैकेज (Mediator)

\n\n

यदि इंटरफ़ेस अनावश्यक लगते हैं, तो एक तीसरा पैकेज बनाया जा सकता है जो दो विरोधी पैकेजों के बीच "पुल" का काम करेगा।

\n\n

हम पैकेज bridge बनाते हैं:

\n
// bridge/bridge.go\npackage bridge\n\nimport (\n    "notifier"\n    "users"\n)\n\nfunc SendWelcomeToUser(user *users.User) {\n                

ब्लॉग

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