"Contains कहाँ है?" — Go सीखने वालों की पहली समस्या
\n\nसोचिए: आप Go में कोड लिख रहे हैं, आपके पास स्ट्रिंग्स का एक स्लाइस है ["python", "go", "rust", "javascript"], और आपको जाँचना है कि इसमें "go" भाषा है या नहीं। अगर आप Python, Ruby या JavaScript से आए हैं, तो आप अपने आप slice.contains("go") लिखेंगे — और एक लाल कम्पाइलेशन एरर मिलेगी। "ये क्या बकवास है?" — आप सोचेंगे। "हर अच्छे कलेक्शन में contains मेथड होता है!"
शांति, बस शांति। Go में वास्तव में स्लाइस के लिए कोई बिल्ट-इन contains मेथड नहीं है। और यह कोई बग नहीं, बल्कि एक फीचर है। भाषा के डेवलपर्स ने सोचा कि एक सार्वभौमिक फंक्शन सभी विकल्पों (स्ट्रिंग्स, नंबर्स, स्ट्रक्चर्स की तुलना) को कवर नहीं करेगा, और इसे प्रोग्रामर पर छोड़ दिया। यह डरावना लगता है, लेकिन वास्तव में यह सरल और सुरुचिपूर्ण है। इस लेख में, हम Go में स्लाइस के लिए contains फंक्शन लिखना, प्रदर्शन, सामान्य गलतियाँ और तैयार समाधान देखेंगे।
\n\nGo में स्लाइस के लिए contains क्यों नहीं है?
\nGo एक न्यूनतम भाषा है। इसमें जेनेरिक्स (वर्जन 1.18 से पहले) और मेथड ओवरलोडिंग नहीं है। स्लाइस एक ऑब्जेक्ट नहीं है जिसमें मेथड्स हों, बल्कि एक डेटा स्ट्रक्चर है: ऐरे का पॉइंटर, लंबाई और क्षमता। Go डेवलपर्स ने फैसला किया कि contains फंक्शन स्पष्ट होना चाहिए, ताकि प्रोग्रामर को हमेशा पता रहे कि तुलना कैसे हो रही है। इससे बग्स की संख्या कम होती है और कोड पूर्वानुमानित बनता है।
\nइसके अलावा, स्लाइस के लिए contains हमेशा एक लीनियर सर्च (O(n)) होता है, और अगर आप O(1) की उम्मीद कर रहे हैं, तो आप गलत स्ट्रक्चर (map) का उपयोग कर रहे हैं। Go इस जटिलता को छिपाना नहीं चाहता।
\n\nGo में स्लाइस के लिए सबसे आसान contains (मैन्युअल लूप)
\nआइए स्ट्रिंग्स के स्लाइस के लिए contains लिखें। यह क्लासिक तरीका है जो आपको किसी भी production-कोड में दिखेगा:
\n\npackage main\n\nimport "fmt"\n\n// Contains जाँचता है कि एलिमेंट स्लाइस में है या नहीं\nfunc Contains(slice []string, target string) bool {\n for _, item := range slice {\n if item == target {\n return true\n }\n }\n return false\n}\n\nfunc main() {\n languages := []string{"python", "go", "rust", "javascript"}\n fmt.Println(Contains(languages, "go")) // true\n fmt.Println(Contains(languages, "csharp")) // false\n}\n\nसब कुछ सरल है: हम स्लाइस पर लूप चलाते हैं, प्रत्येक आइटम की तुलना खोजे जा रहे आइटम से करते हैं। अगर मिल गया — true, नहीं तो false। महत्वपूर्ण: == ऑपरेटर स्ट्रिंग्स, नंबर्स, बूलियन वैल्यू और पॉइंटर्स के लिए काम करता है। स्ट्रक्चर्स या स्लाइस के अंदर स्लाइस (नेस्टेड) के लिए यह काम नहीं करेगा।
नंबर्स के लिए Contains
\nपूर्णांकों के स्लाइस के लिए कोड लगभग समान है:
\n\nfunc ContainsInt(slice []int, target int) bool {\n for _, v := range slice {\n if v == target {\n return true\n }\n }\n return false\n}\n\nfunc main() {\n numbers := []int{10, 20, 30, 40, 50}\n fmt.Println(ContainsInt(numbers, 30)) // true\n fmt.Println(ContainsInt(numbers, 99)) // false\n}\n\nअसुविधाजनक? हाँ। लेकिन यह Go है — स्पष्टता और सरलता सबसे ऊपर है।
\n\nGo में यूनिवर्सल contains (जेनेरिक्स, Go 1.18+)
\nGo 1.18 के आने के साथ, भाषा में जेनेरिक्स (जनरलाइज़ेशन) आ गए। अब हम किसी भी तुलनीय प्रकार के लिए एक contains फंक्शन लिख सकते हैं:
\n\npackage main\n\nimport "fmt"\n\n// ContainsGeneric किसी भी comparable प्रकार के लिए काम करता है\nfunc ContainsGeneric[T comparable](slice []T, target T) bool {\n for _, item := range slice {\n if item == target {\n return true\n }\n }\n return false\n}\n\nfunc main() {\n strs := []string{"a", "b", "c"}\n ints := []int{1, 2, 3}\n floats := []float64{1.1, 2.2, 3.3}\n\n fmt.Println(ContainsGeneric(strs, "b")) // true\n fmt.Println(ContainsGeneric(ints, 5)) // false\n fmt.Println(ContainsGeneric(floats, 2.2)) // true\n}\n\ncomparable बाधा का मतलब है कि प्रकार == और != ऑपरेटरों को सपोर्ट करता है।