Go में खाली स्लाइस: शुरुआत से ही गलती कैसे न करें
\n\nGo पर हर डेवलपर को देर-सबेर इस सवाल का सामना करना पड़ता है: "खाली स्लाइस को सही तरीके से कैसे इनिशियलाइज़ करें?"। यह एक साधारण काम लगता है, लेकिन सब कुछ इतना स्पष्ट नहीं है। Go के आधिकारिक FAQ और Stack Overflow पर इस विषय पर सैकड़ों टिप्पणियाँ और हज़ारों वोट हैं। क्यों?
\n\nक्योंकि Go में खाली स्लाइस बनाने के दो मौलिक रूप से अलग-अलग तरीके हैं, और उनके बीच का चुनाव प्रदर्शन, कोड की पठनीयता और यहाँ तक कि सीरियलाइज़ेशन के व्यवहार को भी प्रभावित करता है। यदि आप Go में लिख रहे हैं और बिना किसी आश्चर्य के स्वच्छ, कुशल कोड लिखना चाहते हैं — तो यह लेख आपके लिए है।
\n\nहम चर्चा करेंगे:
\n- \n
var s []intऔरs := make([]int, 0)में क्या अंतर है \n - nil-स्लाइस का उपयोग कब करें, और खाली स्लाइस का कब \n
- यह JSON, मेमोरी और प्रदर्शन को कैसे प्रभावित करता है \n
- Go के गुरु और मानक लाइब्रेरी के लेखक क्या कहते हैं \n
दो जुड़वाँ भाई: nil slice बनाम empty slice
\n\nGo में, स्लाइस तीन फ़ील्ड की एक संरचना है: ऐरे का पॉइंटर, लंबाई और क्षमता। जब हम खाली स्लाइस कहते हैं, तो हमारा मतलब 0 लंबाई वाली स्लाइस से होता है। लेकिन हम इसे कैसे बनाते हैं, यह मायने रखता है।
\n\nतरीका 1: var-घोषणा (nil slice)
\n\nvar s []int // s == nil, len(s) == 0, cap(s) == 0\n\nयह nil-स्लाइस है। यह मेमोरी में किसी भी ऐरे की ओर इशारा नहीं करता। फिर भी, आप इस पर append कॉल कर सकते हैं — Go स्वचालित रूप से मेमोरी आवंटित करेगा।
तरीका 2: make-इनिशियलाइज़ेशन (empty slice)
\n\ns := make([]int, 0) // s != nil, len(s) == 0, cap(s) == 0\n\nयह खाली स्लाइस है। यह पहले से ही एक शून्य ऐरे (Go रनटाइम में एक विशेष zerobase) की ओर इशारा करता है।
\n\nपहली नज़र में अंतर ध्यान देने योग्य नहीं है। लेकिन आइए गहराई से देखें।
\n\nकंसोल आउटपुट और JSON — पहला जाल
\n\nइस कोड को चलाने का प्रयास करें:
\n\npackage main\n\nimport (\n "encoding/json"\n "fmt"\n)\n\nfunc main() {\n var nilSlice []int\n emptySlice := make([]int, 0)\n\n fmt.Printf("nilSlice: %v, is nil: %v\\n", nilSlice, nilSlice == nil)\n fmt.Printf("emptySlice: %v, is nil: %v\\n", emptySlice, emptySlice == nil)\n\n // JSON-सीरियलाइज़ेशन\n nilJSON, _ := json.Marshal(nilSlice)\n emptyJSON, _ := json.Marshal(emptySlice)\n\n fmt.Printf("nilSlice JSON: %s\\n", nilJSON)\n fmt.Printf("emptySlice JSON: %s\\n", emptyJSON)\n}\n\nपरिणाम आपको आश्चर्यचकित करेगा:
\n\nnilSlice: [], is nil: true\nemptySlice: [], is nil: false\nnilSlice JSON: null\nemptySlice JSON: []\n\nयह रहा मुख्य आश्चर्य! JSON-सीरियलाइज़ेशन अलग-अलग व्यवहार करता है। यदि आपका API प्रतिक्रिया में [] की अपेक्षा करता है, और आप nil-स्लाइस भेजते हैं — तो क्लाइंट को null मिलेगा। और यह अनुबंधों को तोड़ता है।
कई REST-क्लाइंट (विशेषकर JavaScript पर) सख्ती से जाँच करते हैं: यदि प्रतिक्रिया में एक ऐरे की अपेक्षा है, और null आता है — तो फ्रंटएंड पर त्रुटि हो सकती है या तर्क बाधित हो सकता है।
प्रदर्शन: क्या कोई अंतर है?
\n\nसंक्षिप्त उत्तर: हाँ, लेकिन 99% मामलों में यह नगण्य है।
\n\nजब आप make([]int, 0) का उपयोग करते हैं, तो Go तुरंत स्लाइस संरचना (64-बिट सिस्टम पर 24 बाइट्स) के लिए मेमोरी आवंटित करता है और इसे zerobase से जोड़ता है। var का उपयोग करते समय — आवंटन केवल पहले append पर होता है।
यदि आप एक ऐसी स्लाइस बना रहे हैं जो संभवतः खाली रहेगी, तो nil-स्लाइस एक मेमोरी आवंटन बचाता है। यदि आप निश्चित रूप से जानते हैं कि आप तत्व जोड़ेंगे — तो क्षमता निर्दिष्ट करने वाला make बेहतर प्रदर्शन देगा:
// यदि आप अनुमानित आकार जानते हैं — capacity निर्दिष्ट करें\ns := make([]int, 0, 100) // क्षमता 100, लंबाई 0\nfor i := 0; i < 100; i++ {\n s = append(s, i) // बिना पुनः आवंटन के!\n}\n\nलेकिन अधिकांश अनुप्रयोग कार्यों के लिए, अंतर