गो सरल क्यों लगता है, लेकिन शुरुआती लोगों को तोड़ देता है?
\n\nगो (या Golang) एक ऐसी भाषा है जिसे एक ही उद्देश्य से बनाया गया था: प्रोग्रामर कम परेशान हों। न्यूनतम सिंटैक्स, अंतर्निहित समवर्तीता, तेज़ कंपाइलेशन - ऐसा लगता है कि इसे एक सप्ताह में सीखा जा सकता है। और हाँ, आप सीख सकते हैं। लेकिन "अच्छा कोड लिखना" और "गो में कोड लिखना" दो अलग कहानियाँ हैं।
\n\nशुरुआती अक्सर Python, JavaScript या Java से आदतें लाते हैं और उन्हें गो पर लागू करने की कोशिश करते हैं। परिणाम - ऐसे बग जिन्हें पकड़ना मुश्किल है, रनटाइम में पैनिक, और यह महसूस होना कि "गो कुछ टूटा हुआ है"। स्पॉयलर: गो टूटा नहीं है। बस यह अलग तरह से सोचता है।
\n\nइस लेख में, हम गो सीखने में 5 सबसे आम गलतियों पर चर्चा करेंगे। यदि आप अभी शुरू कर रहे हैं - ध्यान से पढ़ें। यदि आप पहले से ही गो में लिख रहे हैं - जाँच करें कि क्या आप अब भी ये गलतियाँ कर रहे हैं।
\n\nगलती #1: त्रुटियों को अनदेखा करना (और Python की आदत)
\n\nPython या JavaScript में, आप इस बात के आदी हैं कि एक फ़ंक्शन परिणाम लौटा सकता है या अपवाद फेंक सकता है। आप कॉल को try/catch में लपेटते हैं और शांति से रहते हैं। गो में सब कुछ अलग है: यहाँ कोई अपवाद नहीं हैं। केवल लौटाए गए मान हैं, और उनमें से एक त्रुटि है।
\n\nशुरुआती लोगों की सबसे लोकप्रिय गलती result, _ := someFunc() लिखना और त्रुटि के बारे में भूल जाना है। या, इससे भी बदतर, बस इसकी जाँच न करना:
// बुरा: त्रुटि को अनदेखा किया गया\nfile, _ := os.Open("config.yaml")\n// अगर फ़ाइल मौजूद नहीं है - file == nil, और अगली पंक्ति पैनिक के साथ क्रैश हो जाएगी\ndefer file.Close()\n\n\nगो में, त्रुटि कोई डरावनी चीज़ नहीं है। यह सिर्फ एक मान है। इसकी जाँच की जानी चाहिए। हमेशा। बिना किसी अपवाद के।
\n\nसही तरीका क्या है?
\n\n// अच्छा: तुरंत त्रुटि की जाँच करें\nfile, err := os.Open("config.yaml")\nif err != nil {\n log.Fatalf("फ़ाइल खोलने में विफल: %v", err)\n}\ndefer file.Close()\n\n\nयह पागलपन नहीं है। यह अनुशासन है। गो आपको सावधान रहना सिखाता है। यदि आप प्रोडक्शन में त्रुटि को अनदेखा करते हैं - तो इस बात के लिए तैयार रहें कि रात के 3 बजे सेवा क्रैश हो जाएगी, और लॉग में सन्नाटा होगा।
\n\nसलाह: त्रुटि के लिए कभी भी _ का उपयोग न करें, जब तक कि आप 100% सुनिश्चित न हों कि यह कभी नहीं होगी। और वास्तविक कोड में ऐसी स्थितियाँ लगभग नहीं होती हैं।
गलती #2: जहाँ त्रुटि की आवश्यकता है वहाँ पैनिक
\n\nगो में panic और recover तंत्र है। शुरुआती अक्सर इन्हें अपवादों के साथ भ्रमित करते हैं और किसी भी समस्या पर पैनिक फेंकना शुरू कर देते हैं। यह गलती है।
panic प्रोग्राम का आपातकालीन स्टॉप है। यह उन स्थितियों के लिए है जहाँ काम जारी रखना असंभव है: उदाहरण के लिए, शून्य पॉइंटर को डीरेफ़रेंस करना या ऐरे की सीमा से बाहर जाना। बिज़नेस लॉजिक को संभालने के लिए panic का उपयोग करना बुरा व्यवहार है।
// बुरा: त्रुटि के बजाय पैनिक\nfunc divide(a, b int) int {\n if b == 0 {\n panic("शून्य से भाग!")\n }\n return a / b\n}\n\n\nसही तरीका त्रुटि लौटाना है:
\n\n// अच्छा: त्रुटि लौटाएँ\nfunc divide(a, b int) (int, error) {\n if b == 0 {\n return 0, fmt.Errorf("शून्य से भाग")\n }\n return a / b, nil\n}\n\n\npanic का उपयोग केवल वास्तव में गंभीर स्थितियों के लिए करें। बाकी सब कुछ त्रुटियाँ हैं। गो आपको error बिना कारण नहीं देता है।
गलती #3: गोरूटीन के साथ गलत काम और सिंक्रनाइज़ेशन की कमी
\n\nगोरूटीन शायद गो की सबसे अच्छी विशेषता है। लेकिन यह शुरुआती लोगों के लिए सबसे खतरनाक भी है। सामान्य परिदृश्य: आप 1000 गोरूटीन चलाते हैं, एक साझा वेरिएबल में लिखते हैं - और डेटा रेस (data race) मिलता है।
\n\n// बुरा: डेटा रेस\nvar counter int\nfor i := 0; i < 1000; i++ {\n go func() {\n counter++ // असुरक्षित!\n }()\n}\ntime.Sleep(time.Second)\nfmt.Println(counter) // परिणाम अप्रत्याशित\n\n\nयह समस्या क्यों है? क्योंकि counter++ एक परमाणु (atomic) ऑपरेशन नहीं है। इसमें पढ़ना, बढ़ाना और लिखना शामिल है। दो गोरूटीन एक ही मान पढ़ सकती हैं, बढ़ा सकती हैं