Go कोड की डिबगिंग: एक शाम में शुरुआत से विशेषज्ञ तक

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

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

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

आपका Go कोड क्यों क्रैश होता है, और इसे बिना सिरदर्द के कैसे ठीक करें

\n\n

आपने अपनी राय में Go में एक परफेक्ट कोड लिखा है। कंपाइलेशन सफल रहा, टेस्ट ग्रीन हैं... लेकिन प्रोडक्शन में सब कुछ बिखर जाता है। परिचित लगता है? डेवलपमेंट की वास्तविक दुनिया में आपका स्वागत है, जहाँ बग्स शुरुआती लोगों की गलतियाँ नहीं, बल्कि पेशेवर विकास का हिस्सा हैं। आज हम Go कोड की डिबगिंग को इस तरह से समझेंगे कि आप न केवल त्रुटियाँ ढूंढेंगे, बल्कि कोड लिखने के चरण में ही उन्हें रोक पाएंगे।

\n\n

Go एक ऐसी भाषा है जो डेवलपर को डिबगिंग के लिए शक्तिशाली उपकरण "बॉक्स से बाहर" ही देती है। लेकिन कई लोग केवल fmt.Println का उपयोग करते हैं और ईमानदारी से आश्चर्य करते हैं कि उनकी गोरूटीन गर्म छत पर बिल्लियों की तरह क्यों व्यवहार करती हैं। आइए इसे हमेशा के लिए ठीक करें।

\n\n

तकनीक #1: स्मार्ट Print - जब log.Fatal की आवश्यकता नहीं है

\n\n

हाँ, मुझे पता है आप क्या कहेंगे: "मुझे delve की क्या ज़रूरत है जब मैं एक वेरिएबल प्रिंट कर सकता हूँ?" और आप 80% मामलों में सही होंगे। लेकिन समस्या fmt.Println में नहीं है, बल्कि इस बात में है कि आप इसका उपयोग कैसे करते हैं।

\n\n

Println से structured logging पर जाएँ

\n\n

दर्जनों प्रिंट चिपकाने के बजाय, log या slog पैकेज का उपयोग करें (Go 1.21 से उपलब्ध):

\n\n
package main\n\nimport (\n    "log/slog"\n    "os"\n)\n\nfunc main() {\n    logger := slog.New(slog.NewTextHandler(os.Stdout, nil))\n    \n    // बजाय fmt.Println("error:", err) के\n    if err := doSomething(); err != nil {\n        logger.Error("ऑपरेशन विफल", \n            "error", err,\n            "module", "data_processor",\n            "attempt", 3,\n        )\n    }\n}\n
\n\n

यह दृष्टिकोण आपको संरचित लॉग देता है, जिन्हें पार्स करना, फ़िल्टर करना और विश्लेषण करना आसान है। प्रोडक्शन में यह आपको रात के कॉल से बचाएगा।

\n\n

लाइफहैक: डीबग लॉग के लिए सशर्त कंपाइलेशन

\n\n

प्रोडक्शन को अव्यवस्थित न करने के लिए, build tags का उपयोग करें:

\n\n
//go:build debug\n\npackage main\n\nvar debug = true\n
\n\n
//go:build !debug\n\npackage main\n\nvar debug = false\n
\n\n

फ्लैग -tags debug के साथ चलाएँ - विस्तृत लॉग प्राप्त करें। बिना फ्लैग के - स्वच्छ प्रोडक्शन।

\n\n

तकनीक #2: Delve - Go के लिए आपका निजी जासूस

\n\n

अगर print डिबगिंग एक साइकिल है, तो Delve एक Tesla है। यह डिबगर विशेष रूप से Go के लिए बनाया गया है और गोरूटीन, इंटरफ़ेस और यहाँ तक कि generics को भी समझता है। इंस्टॉलेशन सरल है:

\n\n
go install github.com/go-delve/delve/cmd/dlv@latest\n
\n\n

ब्रेकपॉइंट जो सोच सकते हैं

\n\n

Delve आपको केवल breakpoint नहीं, बल्कि सशर्त बिंदु सेट करने की अनुमति देता है:

\n\n
(dlv) break main.go:25 if userID == 42\n(dlv) continue\n
\n\n

डिबगर केवल तभी रुकेगा जब userID 42 के बराबर हो। कल्पना करें कि लूप को डीबग करते समय यह कितना समय बचाता है।

\n\n

गोरूटीन की जाँच

\n\n

Go में सबसे डरावनी चीज़ें deadlock और race condition हैं। Delve सभी सक्रिय गोरूटीन दिखाता है:

\n\n
(dlv) goroutines\n  Goroutine 1 - User: ./main.go:10 main.main (0x109a5b6)\n  Goroutine 2 - User: ./main.go:15 main.worker (0x109a6c8)\n* Goroutine 3 - User: ./main.go:22 main.worker (0x109a6c8)\n
\n\n

तारांकन वर्तमान गोरूटीन दिखाता है। उनके बीच स्विच करें:

\n\n
(dlv) goroutine 2\n(dlv) stack\n
\n\n

मेमोरी के साथ काम: अंदर क्या है देखें

\n\n

कमांड locals सभी स्थानीय वेरिएबल दिखाता है, और print उनके मान प्रकारों के साथ आउटपुट करता है:

\n\n
(dlv) locals\ndata = []int len: 100000, cap: 100000\nresult = map[string]int ["error": 5, "success": 99995]\n(dlv) print data[0:5]\n[]int len: 5, cap: 100000, [42, 17, 89, 3, 256]\n
\n\n

तकनीक #3: pprof प्रोफाइलिंग - अड़चनें ढूँढें

\n\n

आपका कोड काम करता है, लेकिन धीमा है? pprof Go का अंतर्निहित प्रोफाइलर है। यह दिखाएगा कि प्रोग्राम कहाँ "धीमा" है और कहाँ मेमोरी खाता है।

\n\n

HTTP एंडपॉइंट जोड़ें

ब्लॉग

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