Go में 'rune' शब्द के पीछे क्या छिपा है? वर्णों की दुनिया में गोता
\n\nक्या आपने कभी Go कोड देखा है जिसमें रहस्यमय शब्द rune दिखाई देता है? यदि आप Python या JavaScript की दुनिया से आए हैं, तो यह हल्की उलझन पैदा कर सकता है। "यह कैसा जादुई डेटा प्रकार है?" — आप पूछेंगे। आइए इसे एक बार और हमेशा के लिए समझ लें। यह विषय केवल शैक्षणिक नहीं है: रून्स को समझना टेक्स्ट, इमोजी, चित्रलिपि और अंग्रेजी वर्णमाला से परे किसी भी वर्ण के साथ सही ढंग से काम करने की कुंजी है।
यह लेख शुष्क दस्तावेज़ीकरण नहीं है, बल्कि एक जीवंत अन्वेषण है। हम Go, Python में वर्णों के साथ काम करने के दृष्टिकोणों की तुलना करेंगे और C में भी झाँकेंगे। आप जानेंगे कि Go में rune केवल एक 'वर्ण' नहीं है, बल्कि Unicode के साथ काम करने के लिए एक शक्तिशाली उपकरण है, और स्ट्रिंग प्रोसेसिंग करते समय जाल में कैसे न फँसें। चलिए शुरू करते हैं!
\n\n\n\n
समस्या: बाइट हमेशा एक वर्ण क्यों नहीं होता?
\n\nकल्पना करें कि आप एक प्रोग्राम लिख रहे हैं जिसे एक स्ट्रिंग में वर्णों की संख्या गिननी है। भोला दृष्टिकोण: स्ट्रिंग की लंबाई लेना। Python में यह लैटिन वर्णमाला के लिए काम करता है: len("hello") 5 लौटाएगा। लेकिन क्या होगा यदि स्ट्रिंग में सिरिलिक या इमोजी हों?
Go में (अधिकांश आधुनिक भाषाओं की तरह) स्ट्रिंग्स UTF-8 एन्कोडिंग में संग्रहीत होती हैं। इसका मतलब है कि एक वर्ण 1 से 4 बाइट तक ले सकता है। अंग्रेजी अक्षर 'A' — 1 बाइट। रूसी 'Я' — 2 बाइट। इमोजी 🚀 — 4 बाइट। यदि हम केवल बाइट्स गिनेंगे, तो हमें वर्णों की गलत संख्या मिलेगी।
\n\nयहीं पर रूना (rune) मंच पर आती है।
\n\n\n\n
Go में rune क्या है? परिभाषा और आंतरिक संरचना
\n\nआधिकारिक तौर पर: rune int32 प्रकार का एक उपनाम (alias) है। यह एक Unicode कोड पॉइंट (code point) का प्रतिनिधित्व करता है। सरल शब्दों में, यह एक पूर्णांक (0 से 0x10FFFF तक) है जो विश्वव्यापी यूनिकोड मानक में एक वर्ण की विशिष्ट पहचान करता है।
// Go के स्रोत कोड में यह इस तरह दिखता है:\ntype rune = int32\n\nजब आप एकल उद्धरणों में 'A' लिखते हैं, तो Go एक रूना बनाता है (मान 65)। जब आप 'Я' लिखते हैं — यह मान 1071 (0x042F) वाली रूना है। जब आप '🚀' लिखते हैं — यह मान 128640 (0x1F680) वाली रूना है।
byte से मुख्य अंतर:
\n- \n
- byte — यह
uint8है। यह एक बाइट (0-255) का प्रतिनिधित्व करता है। इसका उपयोग कच्चे डेटा, ASCII वर्णों या UTF-8 अनुक्रम के अलग-अलग बाइट्स के साथ काम करने के लिए किया जाता है। \n - rune — यह
int32है। यह एक Unicode वर्ण का प्रतिनिधित्व करता है, भले ही वह मेमोरी में कितने बाइट लेता हो। \n
मुख्य विचार: Go में स्ट्रिंग बाइट्स का एक सेट है। इसमें से वर्णों (रून्स) का सेट प्राप्त करने के लिए, इसे स्पष्ट रूप से रून्स के स्लाइस ([]rune) में बदलना होगा।
\n\n
दृष्टिकोणों की तुलना: Go, Python और C
\n\nGo के दृष्टिकोण की प्रतिभा (या अपरिचितता) को समझने के लिए, आइए इसकी तुलना अन्य भाषाओं से करें।
\n\nGo: स्पष्ट रूपांतरण
\n\nGo में आप हमेशा प्रक्रिया को नियंत्रित करते हैं। स्ट्रिंग बाइट्स है। रूना एक वर्ण है। उनके बीच संक्रमण स्पष्ट है।
\n\npackage main\n\nimport "fmt"\n\nfunc main() {\n s := "Привет, мир! 🚀"\n \n // बाइट्स में लंबाई\n fmt.Println("बाइट:", len(s)) // आउटपुट: 21\n \n // रून्स (वर्णों) में लंबाई\n runes := []rune(s)\n fmt.Println("रून:", len(runes)) // आउटपुट: 13\n \n // रून्स पर पुनरावृत्ति (सही तरीका)\n for i, r := range s {\n fmt.Printf("बाइट इंडेक्स: %d, रून: %c (U+%04X)\\n", i, r, r)\n }\n}\n\nध्यान दें: range के साथ पुनरावृत्ति करते समय, Go स्वचालित रूप से UTF-8 को डिकोड करता है और आपको रून्स और उनके बाइट इंडेक्स देता है। यह सुरक्षित और कुशल है।
Python: अंतर्निहित सुविधा (और छिपे हुए जाल)
\n\nPython 3 में, स्ट्रिंग्स Unicode वर्णों (रून्स के समान) के अनुक्रम हैं। स्ट्रिंग की लंबाई वर्णों की संख्या है। क्या यह आसान लगता है? लेकिन एक बारीकी है।
\n\ns = "Привет, мир! 🚀"\nprint(len(s)) # आउटपुट: 13 (यह सही है)\n\n# लेकिन क्या होगा यदि हम संयुक्त वर्णों का उपयोग करें?\ns2 = "é" # दो तरीके: एक अक्षर (U+00E9) या e + ́ (U+0065 + U+0301)\nprint(len(s2)) # आउटपुट: 1 या 2? यह इस बात पर निर्भर करता है कि स्ट्रिंग कैसे बनाई गई है\n\n\nPython में, स्ट्रिंग की लंबाई "यूनिकोड वर्णों" की संख्या है, लेकिन संयुक्त वर्णों (जैसे e + उच्चारण चिह्न) के मामले में, आपको दो वर्ण मिल सकते हैं जहां एक दिखाई देता है। यह एक ऐसा जाल है जिसके बारे में आपको जानना आवश्यक है।
\n\nC: पूर्ण नियंत्रण (और पूर्ण उत्तरदायित्व)
\n\nC में, वर्ण सिर्फ एक बाइट है (char)। यूनिकोड के साथ काम करने के लिए, आपको wchar_t का उपयोग करना होगा, जो एक विस्तृत वर्ण है (आमतौर पर 32-बिट)। लेकिन एन्कोडिंग और डिकोडिंग का सारा काम आपको स्वयं करना होगा, या mbstowcs जैसे कार्यों का उपयोग करना होगा। बहुत अधिक शक्ति, लेकिन बहुत अधिक जिम्मेदारी भी।
#include \n#include \n#include \n\nint main() {\n setlocale(LC_ALL, "");\n wchar_t *s = L"Привет, мир! 🚀";\n wprintf(L"लंबाई (विस्तृत वर्ण): %lu\\n", wcslen(s)); // आउटपुट: 13\n return 0;\n} \n\nजैसा कि हम देख सकते हैं, Go एक सुनहरा मध्य मार्ग प्रदान करता है: rune के साथ स्पष्टता और सुरक्षा, लेकिन थोपने वाली जटिलता के बिना।
\n\n
Go में rune का व्यावहारिक उपयोग
\n\nयह समझना कि rune केवल int32 है, कई दरवाजे खोलता है। यहां कुछ उदाहरण दिए गए हैं जहां यह ज्ञान विशेष रूप से उपयोगी है:
- \n
- पाठ मान्यता और प्रसंस्करण: क्या आप एक पार्सर या टेक्स्ट एनालाइज़र लिख रहे हैं?
[]runeमें बदलें और आपको एक-एक करके वर्ण मिलेंगे, कई-बाइट अनुक्रमों को डिकोड करने की चिंता किए बिना। \n - स्ट्रिंग्स को छोटा करना: एक स्ट्रिंग को पहले N वर्णों तक छोटा करने के लिए, लेकिन बाइट्स के बीच में न काटें: \n
func truncate(s string, maxRunes int) string {\n runes := []rune(s)\n if len(runes) <= maxRunes {\n return s\n }\n return string(runes[:maxRunes])\n}\n\n- \n
- इमोजी और एन्कोडिंग के विरुद्ध सुरक्षा: इमोजी में अक्सर शून्य-चौड़ाई वाले जॉइनर (ZWJ) होते हैं, जो कई रनों को एक दृश्य वर्ण में जोड़ते हैं। आपकी लंबाई गणना अभी भी अलग-अलग रनों की गणना करेगी, जो हमेशा वांछित नहीं होता है, लेकिन कोड बिंदुओं के स्तर पर काम करने का यह एक आवश्यक पहलू है। \n
\n\n
गहराई: rune बनाम byte, रूपांतरण तालिका
\n\nअंतर को पूरी तरह से समेकित करने के लिए, आइए एक सरल तालिका बनाएं। मान लें कि हमारे पास स्ट्रिंग "Привет" है:
\n\n| अनुक्रमणिका (बाइट) | \nबाइट (हेक्स) | \nरून (Unicode) | \nवर्ण | \n
|---|---|---|---|
| 0 | D0 9F | U+041F | П |
| 2 | D1 80 | U+0440 | р |
| 4 | D0 B8 | U+0438 | и |
| 6 | D0 B2 | U+0432 | в |
| 8 | D0 B5 | U+0435 | е |
| 10 | D1 82 | U+0442 | т |
तालिका स्पष्ट रूप से दिखाती है कि 6 वर्णों को 12 बाइट्स की आवश्यकता है। Go में len("Привет") 12 लौटाएगा, और len([]rune("Привет")) 6 लौटाएगा।
\n\n
मुख्य बिंदुओं का सारांश (TL;DR)
\n\n- \n
- rune Go में
int32के लिए एक alias है, जो एक यूनिकोड कोड पॉइंट (0 से 0x10FFFF) का प्रतिनिधित्व करता है। \n - byte
uint8(0-255) है और कच्चे बाइट्स के साथ काम करने के लिए है। \n - Go में स्ट्रिंग्स UTF-8 में बाइट्स का एक सेट हैं। किसी स्ट्रिंग की लंबाई वर्णों की संख्या के बराबर नहीं है। \n
- रून्स प्राप्त करने के लिए, एक स्ट्रिंग को
[]runeमें बदलें याrangeके साथ पुनरावृत्ति करें (जो स्वचालित रूप से UTF-8 को डिकोड करता है)। \n - हमेशा सोचें: क्या आपको बाइट्स या वर्णों (रून्स) की आवश्यकता है? Go आपको चुनने की अनुमति देता है। \n
\n\n
निष्कर्ष
\n\nGo में rune कोई जादू नहीं है। यह एक स्पष्ट, सुरक्षित और इसके मूल में सरल उपकरण है। rune के माध्यम से यूनिकोड के साथ काम करना आधुनिक प्रोग्रामिंग का एक अनिवार्य हिस्सा है, और Go इसे सही ढंग से और बिना अनावश्यक जटिलता के करने का एक तरीका प्रदान करता है। इसे समझने के बाद, आप टेक्स्ट के साथ काम करने के लिए स्वतंत्र होंगे, चाहे वह अंग्रेजी, रूसी, चीनी या इमोजी का कोई भी संयोजन हो।
उद्यमशील बनो, कोड सीखो, और Go तुम्हारे साथ रहे!