«X does not implement Y»: Go में pointer receiver त्रुटि को समझना

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

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

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

परिचय: Go डेवलपर के लिए सत्य का क्षण

\n\n

यदि आपने कभी Go (Golang) में प्रोग्राम लिखा है और इंटरफ़ेस का उपयोग किया है, तो आपने निश्चित रूप से यह कंपाइलर संदेश देखा होगा:

\n\n
cannot use x (variable of type *MyStruct) as type MyInterface value in assignment:\n*MyStruct does not implement MyInterface (method GetName has a pointer receiver)
\n\n

Stack Overflow पर यह प्रश्न हजारों बार देखा जाता है। नए लोग असमंजस में पड़ जाते हैं, अनुभवी कंधे उचकाते हैं। लेकिन वास्तव में इस त्रुटि के पीछे एक सुंदर और महत्वपूर्ण अवधारणा है: Go भाषा में value receiver और pointer receiver के बीच अंतर।

\n\n

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

\n\n

1. Go में इंटरफ़ेस: एक संक्षिप्त परिचय

\n\n

त्रुटि में गोता लगाने से पहले, आइए याद करें कि Go इंटरफ़ेस कैसे काम करते हैं। Java या C++ के विपरीत, Go में इंटरफ़ेस विधियों का एक सेट है। यदि कोई प्रकार इंटरफ़ेस की सभी विधियों को लागू करता है, तो वह स्वचालित रूप से उस इंटरफ़ेस को संतुष्ट करता है (डक टाइपिंग)।

\n\n

एक सरल इंटरफ़ेस का उदाहरण:

\n\n
type Speaker interface {\n    Speak() string\n}
\n\n

अब एक स्ट्रक्चर और एक विधि परिभाषित करते हैं:

\n\n
type Dog struct {\n    Name string\n}\n\n// Value receiver — विधि स्ट्रक्चर की एक प्रतिलिपि पर काम करती है\nfunc (d Dog) Speak() string {\n    return "भौं! मैं " + d.Name\n}
\n\n

यहाँ, Dog Speaker को लागू करता है। यह Dog और *Dog दोनों के साथ काम करता है:

\n\n
var s Speaker\ns = Dog{Name: "टॉमी"}  // ✅ ठीक है\ns = &Dog{Name: "शेरू"}  // ✅ ठीक है (Go स्वचालित रूप से डीरेफरेंस करता है)
\n\n

अब तक सब सरल है। अब विधि को pointer receiver में बदलते हैं:

\n\n
func (d *Dog) Speak() string {\n    return "भौं! मैं " + d.Name\n}
\n\n

और यहाँ से जादू शुरू होता है।

\n\n

2. Pointer receiver बनाम Value receiver: क्या अंतर है?

\n\n

Go में, विधियों के दो प्रकार के प्राप्तकर्ता (receivers) हो सकते हैं:

\n\n
    \n
  • Value receiver (t Type) — विधि मान की एक प्रतिलिपि प्राप्त करती है।
  • \n
  • Pointer receiver (t *Type) — विधि मूल मान का एक पॉइंटर प्राप्त करती है।
  • \n
\n\n

यह क्यों महत्वपूर्ण है? क्योंकि प्रकार की विधियों का सेट इस बात पर निर्भर करता है कि किस receiver का उपयोग किया गया है।

\n\n

सत्य तालिका:

\n\n
    \n
  • प्रकार T में value receiver वाली सभी विधियाँ हैं (T के लिए)।
  • \n
  • प्रकार *T में value receiver + pointer receiver वाली सभी विधियाँ हैं।
  • \n
\n\n

दूसरे शब्दों में: पॉइंटर को विधियों का एक 'बोनस' सेट मिलता है, जबकि मान में केवल वे विधियाँ होती हैं जो value receiver के साथ घोषित की गई हैं।

\n\n

यह कोई बग नहीं, बल्कि Go डिज़ाइन की एक विशेषता है। कंपाइलर स्वचालित रूप से मान का पता नहीं ले सकता यदि वह एड्रेसेबल नहीं है (उदाहरण के लिए, किसी फ़ंक्शन का परिणाम या लिटरल)।

\n\n

3. त्रुटि का विश्लेषण: «method has a pointer receiver»

\n\n

अपने उदाहरण पर वापस आते हैं। यदि Speak() को *Dog के साथ घोषित किया गया है, तो:

\n\n
var s Speaker\ns = Dog{Name: "टॉमी"}  // ❌ त्रुटि\n// cannot use Dog{...} as Speaker...\n// method has a pointer receiver
\n\n

क्यों? क्योंकि Dog (पॉइंटर नहीं) के पास अपने सेट में Speak() विधि नहीं है। विधि केवल *Dog की है।

\n\n

लेकिन यह काम करता है:

\n\n
s = &Dog{Name: "टॉमी"}  // ✅ ठीक है
\n\n

अब आइए वास्तविक कोड से एक अधिक व्यावहारिक उदाहरण देखें, जो अक्सर Stack Overflow पर देखा जाता है।

\n\n

उदाहरण: डेटा के साथ इंटरफ़ेस और स्ट्रक्चर

\n\n
package main\n\nimport "fmt"\n\ntype User interface {\n    GetID() int\n    SetName(name string)\n}\n\ntype Admin struct {\n    ID   int\                

ब्लॉग

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