Delete key in map: Go में हुड के नीचे यह कैसे काम करता है
\n\nक्या आपने कभी सोचा है कि जब आप Go में delete(myMap, "key") लिखते हैं तो वास्तव में क्या होता है? क्या key मेमोरी से गायब हो जाती है? या वहाँ एक "छेद" रह जाता है? और क्या होगा यदि आप nil map से key हटाते हैं? यदि आपने ये प्रश्न पूछे हैं — तो आप अकेले नहीं हैं। delete key in map विषय ने Stack Overflow पर हज़ारों व्यूज़ प्राप्त किए हैं, और आज हम इस प्रतीत होने वाली सरल क्रिया के हुड के नीचे झाँकेंगे।
इस SEO लेख में, हम समझेंगे कि Go में हैश टेबल (संरचना hmap) कैसे काम करती है, key हटाना कैसे काम करता है, मेमोरी कहाँ जाती है, और लूप में delete से क्यों नहीं डरना चाहिए। चलिए शुरू करते हैं!
संक्षिप्त परिचय: Go में map कैसे काम करती है
\n\nहटाने के बारे में बात करने से पहले, आइए याद करें कि map golang डेटा कैसे संग्रहीत करता है। अंदर से, यह एक हैश टेबल है, संरचना hmap। इसमें "बकेट" (buckets) की एक सरणी होती है, जिनमें से प्रत्येक 8 key-value जोड़े तक संग्रहीत कर सकता है। जब आप एक key जोड़ते हैं, Go हैश की गणना करता है, बकेट ढूंढता है और जोड़ी को अंदर रखता है। यदि बकेट ओवरफ्लो हो जाता है, तो एक ओवरफ्लो बकेट (overflow bucket) श्रृंखला बनाई जाती है।
यह एक क्लासिक कार्यान्वयन है, लेकिन कुछ तरकीबों के साथ, जिनके बारे में हम नीचे चर्चा करेंगे।
\n\nhmap संरचना (सरलीकृत)
\n\ntype hmap struct {\n count int // तत्वों की संख्या\n flags uint8\n B uint8 // बकेटों की संख्या का लघुगणक\n buckets unsafe.Pointer // बकेट सरणी की ओर संकेतक\n oldbuckets unsafe.Pointer // map के बढ़ने पर\n nevacuate uintptr\n // ...\n}\n\nमुख्य बात: buckets एक सतत सरणी है। हटाने से यह सरणी सिकुड़ती नहीं है, बल्कि केवल सेल को "खाली" के रूप में चिह्नित करता है।
Delete key in map: कोड स्तर पर यह कैसे काम करता है
\n\nGo में delete(m, k) कॉल एक बिल्ट-इन फंक्शन है, जो रनटाइम कॉल में कंपाइल होता है। अंदर लगभग निम्नलिखित होता है:
- \n
- key का हैश निकालना — Go key के प्रकार के लिए विशिष्ट हैश फंक्शन का उपयोग करता है। \n
- बकेट ढूंढना — हैश के निचले बिट्स द्वारा बकेट संख्या निर्धारित की जाती है। \n
- रैखिक खोज बकेट के अंदर (और ओवरफ्लो श्रृंखलाओं में) — आवश्यक key वाला सेल ढूंढता है।
- मेमोरी साफ़ करना — Go key और value के लिए मेमोरी को शून्य करता है, ताकि गार्बेज कलेक्टर उन्हें एकत्र कर सके।
- सेल को "खाली" के रूप में चिह्नित करना — एक विशेष फ़्लैग
emptyRestयाemptyOne। - काउंटर घटाना —
m.count--।
यह सब औसतन O(1) में होता है, लेकिन टकरावों के कारण सबसे खराब स्थिति में O(n) हो सकता है।
\n\nकोड उदाहरण: क्रिया में delete
\n\npackage main\n\nimport "fmt"\n\nfunc main() {\n m := map[string]int{\n "apple": 5,\n "banana": 3,\n "cherry": 7,\n }\n\n fmt.Println("हटाने से पहले:", m)\n delete(m, "banana")\n fmt.Println("हटाने के बाद:", m)\n\n // आइए एक गैर-मौजूद key को हटाने का प्रयास करें\n delete(m, "grape") // कुछ नहीं होगा, कोई त्रुटि नहीं\n fmt.Println("गैर-मौजूद key हटाने के बाद:", m)\n}\n\nध्यान दें: गैर-मौजूद key के लिए delete key in map एक सुरक्षित ऑपरेशन है। यह बस कुछ नहीं करता। यह शुरुआती लोगों की सामान्य गलतफहमियों में से एक है।
\n\nमेमोरी का क्या होता है? मिथक और वास्तविकता
\n\nकई डेवलपर्स डरते हैं कि delete के बाद map में "छेद" रह जाते हैं जो मेमोरी लीक का कारण बनते हैं। आइए समझते हैं।
keys और values के लिए मेमोरी
\n\nजब आप एक key हटाते हैं, Go उस तत्व के लिए मेमोरी को शून्य कर देता है। यदि key या value पॉइंटर्स थे या उनमें पॉइंटर्स (स्ट्रिंग्स, स्लाइस, maps) थे, तो गार्बेज कलेक्टर उन्हें एकत्र कर सकेगा। बकेट में सेल स्वयं बनी रहती है, लेकिन खाली चिह्नित हो जाती है।
\n\nइसका मतलब है कि map आकार में कम नहीं होती जब तक कि...