Go में फ़ंक्शन नाम से पहले अजीब कोष्ठक: एक विस्तृत विश्लेषण
\n\nकल्पना करें: आप Go में किसी और का कोड खोलते हैं, और आपको कुछ ऐसा दिखता है जिससे आपकी आँख फड़कने लगती है:
\n\nfunc (u User) Greet() string {\n return "नमस्ते, " + u.Name\n}\n\nरुकिए। फ़ंक्शन नाम से पहले यह (u User) क्या है? Python में विधियों के लिए def greet(self): का उपयोग किया जाता है, Java में — क्लास के अंदर public String greet()। और यहाँ — कुछ कोष्ठक, और उनके अंदर एक प्रकार। बकवास? नहीं, शानदार!
यह संरचना Go की सबसे शक्तिशाली विशेषताओं में से एक है, जो अक्सर शुरुआती लोगों को भ्रमित करती है। वास्तव में, यह receiver (प्राप्तकर्ता) है — Go में ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग को समझने की कुंजी।
\n\nइस लेख में, हम Go कंपाइलर के अंदरूनी हिस्से में झाँकेंगे, समझेंगे कि ये कोष्ठक कैसे काम करते हैं, और क्यों उनके बिना आपका कोड 90 के दशक जैसा दिखेगा। तैयार हैं? चलिए शुरू करते हैं!
\n\nreceiver क्या है और इसकी आवश्यकता क्यों है?
\n\nGo में शास्त्रीय अर्थों में क्लास नहीं हैं। लेकिन इसमें स्ट्रक्चर (struct) और विधियाँ (methods) हैं। फ़ंक्शन नाम से पहले कोष्ठक एक विशिष्ट प्रकार के लिए विधि की घोषणा है। तकनीकी रूप से इसे receiver parameter कहा जाता है।
\n\nसिंटैक्स सरल है:
\nfunc (receiver_name ReceiverType) MethodName(params) return_type {\n // विधि का मुख्य भाग\n}\n\nयहाँ receiver_name एक वेरिएबल है जिसके माध्यम से आप स्ट्रक्चर के फ़ील्ड तक पहुँचते हैं (जैसे Python में self या Java में this)। और ReceiverType आपका प्रकार है (आमतौर पर एक स्ट्रक्चर)।
जीवन से एक उदाहरण:
\npackage main\n\nimport "fmt"\n\ntype User struct {\n Name string\n Age int\n}\n\n// receiver के साथ विधि\nfunc (u User) SayHello() {\n fmt.Printf("नमस्ते! मैं %s हूँ, मेरी उम्र %d वर्ष है।\\n", u.Name, u.Age)\n}\n\nfunc main() {\n user := User{Name: "एलिस", Age: 25}\n user.SayHello() // आउटपुट: नमस्ते! मैं एलिस हूँ, मेरी उम्र 25 वर्ष है।\n}\n\nध्यान दें: हम किसी भी OOP भाषा की तरह डॉट के माध्यम से विधि को कॉल करते हैं। लेकिन अंदरूनी तौर पर Go एक चतुर चाल चलता है।
\n\nValue receiver बनाम Pointer receiver: दिग्गजों की लड़ाई
\n\nGo में दो प्रकार के receiver होते हैं: मान द्वारा (value receiver) और पॉइंटर द्वारा (pointer receiver)। अंतर बहुत बड़ा है, और इसे न समझना बग का एक सामान्य कारण है।
\n\nValue receiver
\nजब आप func (u User) ... लिखते हैं, Go पूरे स्ट्रक्चर की कॉपी बनाता है। विधि ऑब्जेक्ट की कॉपी के साथ काम करती है। विधि के अंदर किए गए बदलाव मूल को प्रभावित नहीं करेंगे।
func (u User) Birthday() {\n u.Age++ // यह केवल कॉपी को बदलेगा!\n}\n\nfunc main() {\n user := User{Name: "बॉब", Age: 30}\n user.Birthday()\n fmt.Println(user.Age) // अभी भी 30! बग?\n}\n\nऐसा कोड त्रुटि के साथ कंपाइल नहीं होगा, लेकिन तार्किक रूप से यह गलत है। आप उम्मीद करते हैं कि उम्र बढ़ेगी, लेकिन वह वैसी ही रहती है। value receiver की दुनिया में आपका स्वागत है!
\n\nPointer receiver
\nयदि आप पॉइंटर का उपयोग करते हैं: func (u *User) ..., विधि को मूल ऑब्जेक्ट का संदर्भ मिलता है। अब बदलाव सभी को दिखाई देंगे।
func (u *User) Birthday() {\n u.Age++ // मूल को बदलते हैं\n}\n\nfunc main() {\n user := &User{Name: "बॉब", Age: 30} // पॉइंटर बनाते हैं\n user.Birthday()\n fmt.Println(user.Age) // 31! काम करता है!\n}\n\nअंगूठे का नियम: यदि विधि स्ट्रक्चर की स्थिति को बदलती है या स्ट्रक्चर बड़ा है (कॉपी करने से बचने के लिए), pointer receiver का उपयोग करें। यदि विधि केवल डेटा पढ़ती है — value receiver का उपयोग करें।
\n\nयह अंदरूनी तौर पर कैसे काम करता है?
\n\nअब सबसे दिलचस्प बात। जब Go कंपाइलर देखता है:
\ntype Rectangle struct {\n Width, Height float64\n}\n\nfunc (r Rectangle) Area() float64 {\n return r.Width * r.Height\n}\n\nयह इसे एक सामान्य फ़ंक्शन में बदल देता है, जहाँ receiver पहला आर्गुमेंट बन जाता है:
\nब्लॉग
पुस्तक अनुशंसाएँ
यह भी पढ़ें