Go में रूना क्या है? दृष्टिकोणों की तुलना और वास्तविक उदाहरण

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

Go में 'rune' शब्द के पीछे क्या छिपा है? वर्णों की दुनिया में गोता

\n\n

क्या आपने कभी Go कोड देखा है जिसमें रहस्यमय शब्द rune दिखाई देता है? यदि आप Python या JavaScript की दुनिया से आए हैं, तो यह हल्की उलझन पैदा कर सकता है। "यह कैसा जादुई डेटा प्रकार है?" — आप पूछेंगे। आइए इसे एक बार और हमेशा के लिए समझ लें। यह विषय केवल शैक्षणिक नहीं है: रून्स को समझना टेक्स्ट, इमोजी, चित्रलिपि और अंग्रेजी वर्णमाला से परे किसी भी वर्ण के साथ सही ढंग से काम करने की कुंजी है।

\n\n

यह लेख शुष्क दस्तावेज़ीकरण नहीं है, बल्कि एक जीवंत अन्वेषण है। हम Go, Python में वर्णों के साथ काम करने के दृष्टिकोणों की तुलना करेंगे और C में भी झाँकेंगे। आप जानेंगे कि Go में rune केवल एक 'वर्ण' नहीं है, बल्कि Unicode के साथ काम करने के लिए एक शक्तिशाली उपकरण है, और स्ट्रिंग प्रोसेसिंग करते समय जाल में कैसे न फँसें। चलिए शुरू करते हैं!

\n\n
\n\n

समस्या: बाइट हमेशा एक वर्ण क्यों नहीं होता?

\n\n

कल्पना करें कि आप एक प्रोग्राम लिख रहे हैं जिसे एक स्ट्रिंग में वर्णों की संख्या गिननी है। भोला दृष्टिकोण: स्ट्रिंग की लंबाई लेना। Python में यह लैटिन वर्णमाला के लिए काम करता है: len("hello") 5 लौटाएगा। लेकिन क्या होगा यदि स्ट्रिंग में सिरिलिक या इमोजी हों?

\n\n

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 तक) है जो विश्वव्यापी यूनिकोड मानक में एक वर्ण की विशिष्ट पहचान करता है।

\n\n
// Go के स्रोत कोड में यह इस तरह दिखता है:\ntype rune = int32
\n\n

जब आप एकल उद्धरणों में 'A' लिखते हैं, तो Go एक रूना बनाता है (मान 65)। जब आप 'Я' लिखते हैं — यह मान 1071 (0x042F) वाली रूना है। जब आप '🚀' लिखते हैं — यह मान 128640 (0x1F680) वाली रूना है।

\n\n

byte से मुख्य अंतर:

\n
    \n
  • byte — यह uint8 है। यह एक बाइट (0-255) का प्रतिनिधित्व करता है। इसका उपयोग कच्चे डेटा, ASCII वर्णों या UTF-8 अनुक्रम के अलग-अलग बाइट्स के साथ काम करने के लिए किया जाता है।
  • \n
  • rune — यह int32 है। यह एक Unicode वर्ण का प्रतिनिधित्व करता है, भले ही वह मेमोरी में कितने बाइट लेता हो।
  • \n
\n\n

मुख्य विचार: Go में स्ट्रिंग बाइट्स का एक सेट है। इसमें से वर्णों (रून्स) का सेट प्राप्त करने के लिए, इसे स्पष्ट रूप से रून्स के स्लाइस ([]rune) में बदलना होगा।

\n\n
\n\n

दृष्टिकोणों की तुलना: Go, Python और C

\n\n

Go के दृष्टिकोण की प्रतिभा (या अपरिचितता) को समझने के लिए, आइए इसकी तुलना अन्य भाषाओं से करें।

\n\n

Go: स्पष्ट रूपांतरण

\n\n

Go में आप हमेशा प्रक्रिया को नियंत्रित करते हैं। स्ट्रिंग बाइट्स है। रूना एक वर्ण है। उनके बीच संक्रमण स्पष्ट है।

\n\n
package 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 को डिकोड करता है और आपको रून्स और उनके बाइट इंडेक्स देता है। यह सुरक्षित और कुशल है।

\n\n

Python: अंतर्निहित सुविधा (और छिपे हुए जाल)

\n\n

Python 3 में, स्ट्रिंग्स Unicode वर्णों (रून्स के समान) के अनुक्रम हैं। स्ट्रिंग की लंबाई वर्णों की संख्या है। क्या यह आसान लगता है? लेकिन एक बारीकी है।

\n\n
s = "Привет, мир! 🚀"\nprint(len(s))  # आउटपुट: 13 (यह सही है)\n\n# लेकिन क्या होगा यदि हम संयुक्त वर्णों का उपयोग करें?\ns2 = "é"  # दो तरीके: एक अक्षर (U+00E9) या e + ́ (U+0065 + U+0301)\nprint(len(s2))  # आउटपुट: 1 या 2? यह इस बात पर निर्भर करता है कि स्ट्रिंग कैसे बनाई गई है\n
\n\n

Python में, स्ट्रिंग की लंबाई "यूनिकोड वर्णों" की संख्या है, लेकिन संयुक्त वर्णों (जैसे e + उच्चारण चिह्न) के मामले में, आपको दो वर्ण मिल सकते हैं जहां एक दिखाई देता है। यह एक ऐसा जाल है जिसके बारे में आपको जानना आवश्यक है।

\n\n

C: पूर्ण नियंत्रण (और पूर्ण उत्तरदायित्व)

\n\n

C में, वर्ण सिर्फ एक बाइट है (char)। यूनिकोड के साथ काम करने के लिए, आपको wchar_t का उपयोग करना होगा, जो एक विस्तृत वर्ण है (आमतौर पर 32-बिट)। लेकिन एन्कोडिंग और डिकोडिंग का सारा काम आपको स्वयं करना होगा, या mbstowcs जैसे कार्यों का उपयोग करना होगा। बहुत अधिक शक्ति, लेकिन बहुत अधिक जिम्मेदारी भी।

\n\n
#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
\n\n

Go में rune का व्यावहारिक उपयोग

\n\n

यह समझना कि rune केवल int32 है, कई दरवाजे खोलता है। यहां कुछ उदाहरण दिए गए हैं जहां यह ज्ञान विशेष रूप से उपयोगी है:

\n\n
    \n
  • पाठ मान्यता और प्रसंस्करण: क्या आप एक पार्सर या टेक्स्ट एनालाइज़र लिख रहे हैं? []rune में बदलें और आपको एक-एक करके वर्ण मिलेंगे, कई-बाइट अनुक्रमों को डिकोड करने की चिंता किए बिना।
  • \n
  • स्ट्रिंग्स को छोटा करना: एक स्ट्रिंग को पहले N वर्णों तक छोटा करने के लिए, लेकिन बाइट्स के बीच में न काटें:
  • \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
\n\n

गहराई: rune बनाम byte, रूपांतरण तालिका

\n\n

अंतर को पूरी तरह से समेकित करने के लिए, आइए एक सरल तालिका बनाएं। मान लें कि हमारे पास स्ट्रिंग "Привет" है:

\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
अनुक्रमणिका (बाइट)बाइट (हेक्स)रून (Unicode)वर्ण
0D0 9FU+041FП
2D1 80U+0440р
4D0 B8U+0438и
6D0 B2U+0432в
8D0 B5U+0435е
10D1 82U+0442т
\n\n

तालिका स्पष्ट रूप से दिखाती है कि 6 वर्णों को 12 बाइट्स की आवश्यकता है। Go में len("Привет") 12 लौटाएगा, और len([]rune("Привет")) 6 लौटाएगा।

\n\n
\n\n

मुख्य बिंदुओं का सारांश (TL;DR)

\n\n
    \n
  1. rune Go में int32 के लिए एक alias है, जो एक यूनिकोड कोड पॉइंट (0 से 0x10FFFF) का प्रतिनिधित्व करता है।
  2. \n
  3. byte uint8 (0-255) है और कच्चे बाइट्स के साथ काम करने के लिए है।
  4. \n
  5. Go में स्ट्रिंग्स UTF-8 में बाइट्स का एक सेट हैं। किसी स्ट्रिंग की लंबाई वर्णों की संख्या के बराबर नहीं है।
  6. \n
  7. रून्स प्राप्त करने के लिए, एक स्ट्रिंग को []rune में बदलें या range के साथ पुनरावृत्ति करें (जो स्वचालित रूप से UTF-8 को डिकोड करता है)।
  8. \n
  9. हमेशा सोचें: क्या आपको बाइट्स या वर्णों (रून्स) की आवश्यकता है? Go आपको चुनने की अनुमति देता है।
  10. \n
\n\n
\n\n

निष्कर्ष

\n\n

Go में rune कोई जादू नहीं है। यह एक स्पष्ट, सुरक्षित और इसके मूल में सरल उपकरण है। rune के माध्यम से यूनिकोड के साथ काम करना आधुनिक प्रोग्रामिंग का एक अनिवार्य हिस्सा है, और Go इसे सही ढंग से और बिना अनावश्यक जटिलता के करने का एक तरीका प्रदान करता है। इसे समझने के बाद, आप टेक्स्ट के साथ काम करने के लिए स्वतंत्र होंगे, चाहे वह अंग्रेजी, रूसी, चीनी या इमोजी का कोई भी संयोजन हो।

\n\n

उद्यमशील बनो, कोड सीखो, और Go तुम्हारे साथ रहे!

ब्लॉग

पुस्तक अनुशंसाएँ