Go में फ़ंक्शन नाम से पहले अजीब कोष्ठक: एक विस्तृत विश्लेषण

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

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

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

Go में फ़ंक्शन नाम से पहले अजीब कोष्ठक: एक विस्तृत विश्लेषण

\n\n

कल्पना करें: आप Go में किसी और का कोड खोलते हैं, और आपको कुछ ऐसा दिखता है जिससे आपकी आँख फड़कने लगती है:

\n\n
func (u User) Greet() string {\n    return "नमस्ते, " + u.Name\n}
\n\n

रुकिए। फ़ंक्शन नाम से पहले यह (u User) क्या है? Python में विधियों के लिए def greet(self): का उपयोग किया जाता है, Java में — क्लास के अंदर public String greet()। और यहाँ — कुछ कोष्ठक, और उनके अंदर एक प्रकार। बकवास? नहीं, शानदार!

\n\n

यह संरचना Go की सबसे शक्तिशाली विशेषताओं में से एक है, जो अक्सर शुरुआती लोगों को भ्रमित करती है। वास्तव में, यह receiver (प्राप्तकर्ता) है — Go में ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग को समझने की कुंजी।

\n\n

इस लेख में, हम Go कंपाइलर के अंदरूनी हिस्से में झाँकेंगे, समझेंगे कि ये कोष्ठक कैसे काम करते हैं, और क्यों उनके बिना आपका कोड 90 के दशक जैसा दिखेगा। तैयार हैं? चलिए शुरू करते हैं!

\n\n

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

\n\n

Go में शास्त्रीय अर्थों में क्लास नहीं हैं। लेकिन इसमें स्ट्रक्चर (struct) और विधियाँ (methods) हैं। फ़ंक्शन नाम से पहले कोष्ठक एक विशिष्ट प्रकार के लिए विधि की घोषणा है। तकनीकी रूप से इसे receiver parameter कहा जाता है।

\n\n

सिंटैक्स सरल है:

\n
func (receiver_name ReceiverType) MethodName(params) return_type {\n    // विधि का मुख्य भाग\n}
\n\n

यहाँ receiver_name एक वेरिएबल है जिसके माध्यम से आप स्ट्रक्चर के फ़ील्ड तक पहुँचते हैं (जैसे Python में self या Java में this)। और ReceiverType आपका प्रकार है (आमतौर पर एक स्ट्रक्चर)।

\n\n

जीवन से एक उदाहरण:

\n
package 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\n

Value receiver बनाम Pointer receiver: दिग्गजों की लड़ाई

\n\n

Go में दो प्रकार के receiver होते हैं: मान द्वारा (value receiver) और पॉइंटर द्वारा (pointer receiver)। अंतर बहुत बड़ा है, और इसे न समझना बग का एक सामान्य कारण है।

\n\n

Value receiver

\n

जब आप func (u User) ... लिखते हैं, Go पूरे स्ट्रक्चर की कॉपी बनाता है। विधि ऑब्जेक्ट की कॉपी के साथ काम करती है। विधि के अंदर किए गए बदलाव मूल को प्रभावित नहीं करेंगे।

\n\n
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\n

Pointer receiver

\n

यदि आप पॉइंटर का उपयोग करते हैं: func (u *User) ..., विधि को मूल ऑब्जेक्ट का संदर्भ मिलता है। अब बदलाव सभी को दिखाई देंगे।

\n\n
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 कंपाइलर देखता है:

\n
type Rectangle struct {\n    Width, Height float64\n}\n\nfunc (r Rectangle) Area() float64 {\n    return r.Width * r.Height\n}
\n\n

यह इसे एक सामान्य फ़ंक्शन में बदल देता है, जहाँ receiver पहला आर्गुमेंट बन जाता है:

\n


                
                

ब्लॉग

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