इस सप्ताह, मैं गोलांग के लिए एपीआई रैपर पैकेजों में से एक पर काम कर रहा था, और यह यूआरएल एन्कोडेड मानों के साथ पोस्ट अनुरोध भेजने, कुकीज़ सेट करने और सभी मजेदार चीजों से संबंधित था। हालाँकि, जब मैं बॉडी का निर्माण कर रहा था, तो मैं बॉडी के निर्माण के लिए url.Value प्रकार का उपयोग कर रहा था, और कुंजी-मूल्य जोड़े को जोड़ने और सेट करने के लिए इसका उपयोग कर रहा था। हालाँकि, मुझे कुछ हिस्सों में वायर्ड शून्य पॉइंटर संदर्भ त्रुटि मिल रही थी, मैंने सोचा कि यह मेरे द्वारा मैन्युअल रूप से सेट किए गए कुछ वेरिएबल्स के कारण था। हालाँकि, करीब से डीबग करने पर, मुझे एक प्रकार की घोषणा करने और उसे आरंभ करने की एक सामान्य गड़बड़ी या खराब प्रथा का पता चला और इससे शून्य संदर्भ त्रुटियाँ हो रही हैं।
इस पोस्ट में, मैं बताऊंगा कि मानचित्र क्या हैं, मानचित्र कैसे बनाएं, और विशेष रूप से उन्हें ठीक से कैसे घोषित और प्रारंभ किया जाए। गोलांग में मानचित्रों या किसी समान डेटा प्रकार की घोषणा और आरंभीकरण के बीच उचित अंतर बनाएं।
गोलांग में एक नक्शा या हैशमैप एक बुनियादी डेटा प्रकार है जो हमें कुंजी-मूल्य जोड़े को संग्रहीत करने की अनुमति देता है। हुड के नीचे, यह एक हेडर मैप जैसी डेटा संरचना है जो बकेट रखती है, जो मूल रूप से बकेट एरेज़ (सन्निहित मेमोरी) के संकेतक हैं। इसमें हैश कोड होते हैं जो वास्तविक कुंजी-मूल्य जोड़े को संग्रहीत करते हैं, और यदि कुंजी की संख्या के साथ करंट ओवरफ्लो हो जाता है तो नए बकेट के लिए पॉइंटर होते हैं। यह वास्तव में एक स्मार्ट डेटा संरचना है जो लगभग निरंतर समय पहुंच प्रदान करती है।
गोलांग में एक सरल मानचित्र बनाने के लिए, आप स्ट्रिंग और पूर्णांक के मानचित्र का उपयोग करके अक्षर आवृत्ति काउंटर का एक उदाहरण ले सकते हैं। मानचित्र अक्षरों को कुंजी के रूप में और उनकी आवृत्ति को मान के रूप में संग्रहीत करेगा।
package main import "fmt" func main() { words := "hello how are you" letters := map[string]int{} for _, word := range words { wordCount[word] } fmt.Println("Word counts:") for word, count := range wordCount { fmt.Printf("%s: %d\n", word, count) } }
$ go run main.go Word counts: e: 2 : 3 w: 1 r: 1 y: 1 u: 1 h: 2 l: 2 o: 3 a: 1
तो, मानचित्र को मानचित्र[स्ट्रिंग]int{} के रूप में प्रारंभ करने पर आपको एक खाली मानचित्र मिलेगा। इसका उपयोग कुंजियों और मानों को पॉप्युलेट करने के लिए किया जा सकता है, हम स्ट्रिंग पर पुनरावृति करते हैं, और प्रत्येक वर्ण (रूण) के लिए हम चरित्र के उस बाइट को स्ट्रिंग में डालते हैं और मान बढ़ाते हैं, int के लिए शून्य मान 0 है, इसलिए डिफ़ॉल्ट रूप से यदि कुंजी मौजूद नहीं है, तो यह शून्य होगा, हालांकि यह दोधारी तलवार की तरह है, हम कभी नहीं जानते कि कुंजी मान 0 के साथ मानचित्र में मौजूद है या कुंजी मौजूद नहीं है लेकिन डिफ़ॉल्ट मान 0 है। उसके लिए, आपको चाहिए जांचें कि कुंजी मानचित्र में मौजूद है या नहीं।
अधिक जानकारी के लिए, आप मेरे गोलांग मानचित्र पोस्ट को विस्तार से देख सकते हैं।
प्रोग्रामिंग भाषा में किसी भी वेरिएबल को घोषित करने और आरंभ करने में अंतर होता है और अंतर्निहित प्रकार के कार्यान्वयन के साथ और भी बहुत कुछ करना पड़ता है। प्राथमिक डेटा प्रकारों जैसे इंट, स्ट्रिंग, फ्लोट आदि के मामले में डिफ़ॉल्ट/शून्य मान होते हैं, इसलिए यह चर की घोषणा और आरंभीकरण के समान है। हालाँकि, मानचित्रों और स्लाइस के मामले में, घोषणा केवल यह सुनिश्चित कर रही है कि वेरिएबल प्रोग्राम के दायरे में उपलब्ध है, हालाँकि आरंभीकरण के लिए इसे इसके डिफ़ॉल्ट/शून्य मान या वास्तविक मान पर सेट किया जा रहा है जिसे असाइन किया जाना चाहिए।
इसलिए, घोषणा केवल प्रोग्राम के दायरे में वेरिएबल उपलब्ध कराती है। मानचित्रों और स्लाइसों के लिए, आरंभीकरण के बिना एक चर घोषित करने से यह शून्य पर सेट हो जाता है, जिसका अर्थ है कि यह कोई आवंटित मेमोरी नहीं दिखाता है और इसका सीधे उपयोग नहीं किया जा सकता है।
जबकि इनिशियलाइज़ेशन मेमोरी आवंटित करता है और वेरिएबल को प्रयोग करने योग्य स्थिति में सेट करता है। मानचित्रों और स्लाइसों के लिए, आपको myMap = make(map[keyType]valueType) या स्लाइस = []type{} जैसे सिंटैक्स का उपयोग करके उन्हें स्पष्ट रूप से प्रारंभ करने की आवश्यकता है। इस आरंभीकरण के बिना, मानचित्र या स्लाइस का उपयोग करने का प्रयास रनटाइम त्रुटियों को जन्म देगा, जैसे शून्य मानचित्र या स्लाइस तक पहुंचने या संशोधित करने के लिए घबराहट।
आइए मानचित्र के मूल्यों पर नजर डालते हैं जब यह घोषित/प्रारंभिक/प्रारंभिक नहीं होता है।
कल्पना करें कि आप एक कॉन्फ़िगरेशन प्रबंधक बना रहे हैं जो मानचित्र से सेटिंग्स पढ़ता है। मानचित्र विश्व स्तर पर घोषित किया जाएगा लेकिन कॉन्फ़िगरेशन लोड होने पर ही प्रारंभ किया जाएगा।
नीचे दिया गया कोड एक मानचित्र पहुंच प्रदर्शित करता है जिसे प्रारंभ नहीं किया गया है।
package main import ( "fmt" "log" ) // Global map to store configuration settings var configSettings map[string]string // Declared but not initialized func main() { // Attempt to get a configuration setting before initializing the map serverPort := getConfigSetting("server_port") fmt.Printf("Server port: %s\n", serverPort) } func getConfigSetting(key string) string { if configSettings == nil { log.Fatal("Configuration settings map is not initialized") } value, exists := configSettings[key] if !exists { return "Setting not found" } return value }
$ go run main.go Server port: Setting not found
नीचे दिया गया कोड एक मानचित्र पहुंच को दर्शाता है जिसे एक ही समय में प्रारंभ किया गया है।
package main import ( "fmt" "log" ) // Global map to store configuration settings var configSettings = map[string]string{ "server_port": "8080", "database_url": "localhost:5432", } func main() { serverPort := getConfigSetting("server_port") fmt.Printf("Server port: %s\n", serverPort) } func getConfigSetting(key string) string { value, exists := configSettings[key] if !exists { return "Setting not found" } return value }
$ go run main.go Server port: 8080
नीचे दिया गया कोड एक मानचित्र पहुंच प्रदर्शित करता है जिसे बाद में प्रारंभ किया गया है।
package main import ( "fmt" "log" ) // Global map to store configuration settings var configSettings map[string]string // declared but not initialized func main() { // Initialize configuration settings initializeConfigSettings() // if the function is not called, the map will be nil // Get a configuration setting safely serverPort := getConfigSetting("server_port") fmt.Printf("Server port: %s\n", serverPort) } func initializeConfigSettings() { if configSettings == nil { configSettings = make(map[string]string) // Properly initialize the map configSettings["server_port"] = "8080" configSettings["database_url"] = "localhost:5432" fmt.Println("Configuration settings initialized") } } func getConfigSetting(key string) string { if configSettings == nil { log.Fatal("Configuration settings map is not initialized") } value, exists := configSettings[key] if !exists { return "Setting not found" } return value }
$ go run main.go Configuration settings initialized Server port: 8080
उपरोक्त कोड में, हमने वैश्विक मानचित्र कॉन्फ़िगसेटिंग्स की घोषणा की, लेकिन उस बिंदु पर इसे प्रारंभ नहीं किया, जब तक कि हम मानचित्र तक पहुंच नहीं चाहते थे। हम मानचित्र को मुख्य फ़ंक्शन में प्रारंभ करते हैं, यह मुख्य फ़ंक्शन कोड के अन्य विशिष्ट भाग हो सकते हैं, और वैश्विक चर configSettings कोड के दूसरे भाग से एक मानचित्र, इसे आवश्यक दायरे में प्रारंभ करके, हम इसे शून्य सूचक पैदा करने से रोकते हैं पहुँच त्रुटियाँ. हम मानचित्र को केवल तभी प्रारंभ करते हैं यदि यह शून्य है यानी इसे कोड में कहीं और प्रारंभ नहीं किया गया है। यह मानचित्र को ओवरराइड करने/स्कोप के अन्य हिस्सों से कॉन्फिग सेट को फ्लश करने से रोकता है।
लेकिन चूंकि यह पॉइंटर्स से संबंधित है, इसलिए इसके अपने नुकसान भी हैं, जैसे कि जब मानचित्र प्रारंभ नहीं होता है तो शून्य पॉइंटर्स तक पहुंच नहीं होती है।
आइए एक उदाहरण देखें, एक वास्तविक मामला जहां ऐसा हो सकता है।
package main import ( "fmt" "net/url" ) func main() { var vals url.Values vals.Add("foo", "bar") fmt.Println(vals) }
इसके परिणामस्वरूप रनटाइम घबराहट होगी।
$ go run main.go panic: assignment to entry in nil map goroutine 1 [running]: net/url.Values.Add(...) /usr/local/go/src/net/url/url.go:902 main.main() /home/meet/code/playground/go/main.go:10 0x2d exit status 2
ऐसा इसलिए है क्योंकि url.Values स्ट्रिंग का एक मानचित्र और स्ट्रिंग मानों की एक सूची है। चूंकि अंतर्निहित प्रकार मानों के लिए एक मानचित्र है, और उदाहरण में, हमने केवल url.Values प्रकार के साथ वेरिएबल मान घोषित किया है, यह एक शून्य संदर्भ को इंगित करेगा, इसलिए प्रकार में मान जोड़ने पर संदेश। इसलिए, मानचित्र डेटा प्रकार की घोषणा या आरंभीकरण करते समय मेक का उपयोग करना एक अच्छा अभ्यास है। यदि आप सुनिश्चित नहीं हैं कि अंतर्निहित प्रकार मानचित्र है तो आप उस प्रकार के खाली मान को आरंभ करने के लिए टाइप {} का उपयोग कर सकते हैं।
package main import ( "fmt" "net/url" ) func main() { vals := make(url.Values) // OR // vals := url.Values{} vals.Add("foo", "bar") fmt.Println(vals) }
$ go run urlvals.go map[foo:[bar]] foo=bar
गोलांग टीम द्वारा मानचित्र को प्रारंभ करते समय मेक फ़ंक्शन का उपयोग करने की भी अनुशंसा की जाती है। इसलिए, या तो मैप्स, स्लाइस और चैनल के लिए मेक का उपयोग करें, या टाइप {} के साथ खाली वैल्यू वेरिएबल को इनिशियलाइज़ करें। ये दोनों समान रूप से काम करते हैं, लेकिन बाद वाला आमतौर पर संरचनाओं पर भी लागू होता है।
गोलांग में नक्शों को घोषित करने और आरंभ करने के बीच के अंतर को समझना किसी भी डेवलपर के लिए आवश्यक है, न केवल गोलांग में, बल्कि सामान्य तौर पर। जैसा कि हमने पता लगाया है, किसी मैप वैरिएबल को आरंभ किए बिना घोषित करने से रनटाइम त्रुटियां हो सकती हैं, जैसे शून्य मैप तक पहुंचने या संशोधित करने का प्रयास करते समय घबराहट। मानचित्र को प्रारंभ करने से यह सुनिश्चित होता है कि यह मेमोरी में ठीक से आवंटित है और उपयोग के लिए तैयार है, जिससे इन नुकसानों से बचा जा सकता है।
सर्वोत्तम प्रथाओं का पालन करके - जैसे कि मेक फ़ंक्शन का उपयोग करना या टाइप के साथ आरंभ करना {} - आप अप्रारंभीकृत मानचित्रों से संबंधित सामान्य समस्याओं को रोक सकते हैं। हमेशा सुनिश्चित करें कि अप्रत्याशित शून्य पॉइंटर डेरेफ़रेंस से सुरक्षा के लिए उपयोग से पहले मानचित्र और स्लाइस को स्पष्ट रूप से प्रारंभ किया गया है
इस पोस्ट को पढ़ने के लिए धन्यवाद, यदि आपके कोई प्रश्न, प्रतिक्रिया और सुझाव हैं, तो बेझिझक उन्हें टिप्पणियों में छोड़ दें।
हैप्पी कोडिंग :)
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3