हमेशा की समस्या: बाईं ओर '0' या 'दाईं ओर शिफ्ट'?
\n\nक्या आपने कभी सोचा है कि SQL क्वेरी में ऑर्डर नंबर 00042 जैसे क्यों दिखते हैं, और लॉग में 23:05:07 जैसे? यह आसान है: शून्य से भरी संख्याएँ चौड़ाई में संरेखित होती हैं और सॉर्टिंग को नहीं तोड़ती हैं। लेकिन Go में, Python या JavaScript के विपरीत, कोई बिल्ट-इन zfill मेथड नहीं है। और यहीं से मज़ा शुरू होता है।
Stack Overflow पर सवाल "How to pad a number with zeros when printing?" को हज़ारों व्यूज़ और दर्जनों जवाब मिले हैं। लोग सिर्फ़ हल नहीं, बल्कि तेज़ हल ढूंढ रहे हैं। इस लेख में हम Go में संख्याओं को शून्य से भरने के सभी तरीकों को समझेंगे, उनकी परफ़ॉर्मेंस तुलना करेंगे और आपके प्रोजेक्ट के लिए सबसे अच्छा तरीका चुनेंगे।
\n\nGo डेवलपर के लिए यह क्यों ज़रूरी है?
\n\nGo सिस्टम प्रोग्रामिंग की भाषा है, जहाँ हर नैनोसेकंड मायने रखता है। अगर आप हाई-लोड सर्विस लिख रहे हैं, तो गलत स्ट्रिंग फ़ॉर्मेटिंग एक बाधा बन सकती है। खासकर जब आप प्रति सेकंड हज़ारों संख्याओं को फ़ॉर्मेट कर रहे हों।
\n\n- \n
- लॉगिंग: टाइमस्टैम्प, रिक्वेस्ट ID, एरर कोड। \n
- रिपोर्ट जनरेशन: CSV, JSON, टेबल। \n
- नेटवर्क प्रोटोकॉल: फिक्स्ड लेंथ फ़ील्ड। \n
- गेम्स और ग्राफ़िक्स: कंसोल में टेक्स्ट अलाइनमेंट। \n
परफ़ॉर्मेंस को नज़रअंदाज़ करने से आपकी सर्विस 10% समय सिर्फ़ नंबर फ़ॉर्मेट करने में बर्बाद कर सकती है। विश्वास नहीं होता? चलिए जाँचते हैं।
\n\nतरीका #1: क्लासिक fmt.Sprintf
\n\nसबसे आसान और अक्सर सुझाया जाने वाला तरीका है fmt.Sprintf का उपयोग फ़ॉर्मेट स्पेसिफ़ायर %0Xd के साथ, जहाँ X शून्य सहित संख्या की कुल चौड़ाई है।
package main\n\nimport "fmt"\n\nfunc main() {\n num := 42\n padded := fmt.Sprintf("%05d", num)\n fmt.Println(padded) // आउटपुट: 00042\n}\n\n\nयहाँ %05d का मतलब है: "संख्या को दशमलव पूर्णांक के रूप में प्रिंट करें, बाईं ओर शून्य भरें जब तक कुल चौड़ाई 5 कैरेक्टर न हो जाए"। अगर संख्या पहले से लंबी है (जैसे 123456), तो शून्य नहीं जोड़े जाते — चौड़ाई को नज़रअंदाज़ कर दिया जाता है।
फ़ायदे:
\n- \n
- सरल और पढ़ने में आसान। \n
- नेगेटिव नंबर को सपोर्ट करता है (साइन शून्य के बाईं ओर होगा)। \n
- विभिन्न टाइप के साथ काम करता है:
%05dint के लिए,%05.2ffloat के लिए। \n
नुकसान:
\n- \n
fmtके अंदर रिफ़्लेक्शन का उपयोग करता है — धीमा। \n- एक अतिरिक्त स्ट्रिंग और interface{} बनाता है। \n
- हॉट पाथ के लिए उपयुक्त नहीं। \n
तरीका #2: तेज़ strconv.FormatInt मैन्युअल पैडिंग के साथ
\n\nअगर परफ़ॉर्मेंस महत्वपूर्ण है, तो strconv पैकेज का उपयोग करें। यह सीधे बाइट्स के साथ काम करता है, बिना रिफ़्लेक्शन के।
package main\n\nimport (\n "fmt"\n "strconv"\n "strings"\n)\n\nfunc padNumber(num int64, width int) string {\n s := strconv.FormatInt(num, 10)\n if len(s) >= width {\n return s\n }\n return strings.Repeat("0", width-len(s)) + s\n}\n\nfunc main() {\n fmt.Println(padNumber(42, 5)) // 00042\n}\n\n\nफ़ायदे:
\n- \n
fmt.Sprintfसे 2-3 गुना तेज़। \n- कोई रिफ़्लेक्शन नहीं। \n
- लॉजिक पर पूरा नियंत्रण। \n
नुकसान:
\n- \n
- ज़्यादा कोड। \n
- नेगेटिव नंबर को अलग से हैंडल करना होगा (साइन शून्य के बाईं ओर)। \n
strings.Repeatएक नई स्ट्रिंग बनाता है — इसे और ऑप्टिमाइज़ किया जा सकता है। \n
तरीका #3: strings.Builder के साथ अधिकतम परफ़ॉर्मेंस
\n\nउन लोगों के लिए जो हर आखिरी परफ़ॉर्मेंस निचोड़ना चाहते हैं, एक तरीका है बिना अतिरिक्त एलोकेशन के — strings.Builder का उपयोग करें और पहले से बफ़र आवंटित करें।
package main\n\nimport (\n "fmt"\n "strconv"\n "strings"\n)\n\nfunc padNumberFast(num int64, width int) string {\n s := strconv.FormatInt(num, 10)\n if len(s)