Go में त्रुटि प्रबंधन: try/catch के बिना दर्शन
Go (Golang) की दुनिया में कई डेवलपर्स के लिए परिचित try/catch तंत्र नहीं है। यह कोई संयोग नहीं, बल्कि एक सोचा-समझा आर्किटेक्चरल निर्णय है। भाषा के निर्माताओं ने माना कि स्पष्ट त्रुटि प्रबंधन कोड को अधिक विश्वसनीय और पठनीय बनाता है। कॉल स्टैक में अपवादों को छिपाने के बजाय, Go प्रोग्रामर को हर संभावित खतरनाक ऑपरेशन के परिणाम की जाँच करने के लिए प्रोत्साहित करता है। इस लेख में, हम Go में त्रुटि प्रबंधन के सभी मुख्य दृष्टिकोणों को समझेंगे: बुनियादी error से लेकर शक्तिशाली panic और recover तक, और यह भी दिखाएंगे कि ऐसा कोड कैसे लिखें जो सबसे अनुपयुक्त क्षण में क्रैश न हो।
1. मूल तंत्र: error इंटरफ़ेस
Go में त्रुटि प्रबंधन का आधार बिल्ट-इन error इंटरफ़ेस है। इसमें केवल एक विधि है:
type error interface { Error() string}कोई भी फ़ंक्शन जो विफल हो सकता है, उसे अंतिम मान के रूप में error लौटाना चाहिए। यदि कोई त्रुटि नहीं है तो nil लौटाने की प्रथा है, और यदि कोई विफलता हुई है तो गैर-शून्य मान लौटाना चाहिए।
बुनियादी प्रबंधन का उदाहरण:
package main
import ( "errors" "fmt")
func divide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("शून्य से विभाजन संभव नहीं") } return a / b, nil}
func main() { result, err := divide(10, 0) if err != nil { fmt.Println("त्रुटि:", err) return } fmt.Println("परिणाम:", result)}यह Go में try/catch का एनालॉग है — स्पष्ट जाँच if err != nil। यह दृष्टिकोण डेवलपर को हर कदम पर त्रुटियों के बारे में सोचने के लिए मजबूर करता है।
2. कस्टम त्रुटि प्रकार और रैपिंग (wrapping)
अक्सर केवल विवरण के साथ एक स्ट्रिंग लौटाना पर्याप्त नहीं होता है। संदर्भ देना आवश्यक है: त्रुटि कहाँ हुई, कौन से पैरामीटर पास किए गए। इसके लिए स्वयं के त्रुटि प्रकार बनाए जाते हैं।
कस्टम त्रुटि बनाना:
type DivisionError struct { Dividend float64 Divisor float64 Message string}
func (e *DivisionError) Error() string { return fmt.Sprintf("विभाजन त्रुटि: %s (भाज्य: %f, भाजक: %f)", e.Message, e.Dividend, e.Divisor)}
func safeDivide(a, b float64) (float64, error) { if b == 0 { return 0, &DivisionError{Dividend: a, Divisor: b, Message: "भाजक शून्य है"} } return a / b, nil}त्रुटियों को लपेटना (wrapping):
Go 1.13 से शुरू करके, संदर्भ जोड़ते हुए एक त्रुटि को दूसरे में लपेटने की क्षमता आई:
import "fmt"
func readConfig(path string) error { file, err := openFile(path) if err != nil { return fmt.Errorf("कॉन्फ़िग %s पढ़ने में विफल: %w", path, err) } defer file.Close() // ... फ़ाइल पढ़ना return nil}निर्देश %w त्रुटियों की एक श्रृंखला बनाता है। बाद में आप errors.Is() और errors.As() का उपयोग करके जाँच सकते हैं कि त्रुटि किसी विशिष्ट प्रकार की है या नहीं।
3. Panic और Recover: आपातकालीन स्थितियाँ
कभी-कभी ऐसा कुछ होता है जो सिद्धांत रूप में नहीं होना चाहिए — ऐरे की सीमा से बाहर जाना, शून्य पॉइंटर को डीरेफरेंस करना। ऐसे मामलों में Go panic का उपयोग करता है। यह try/catch का विकल्प नहीं है, बल्कि गंभीर, अपरिवर्तनीय त्रुटियों के लिए एक तंत्र है।
panic का उदाहरण:
func main() { arr := []int{1, 2, 3} fmt.Println(arr[10]) // panic: runtime error: index out of range}हालाँकि, यदि आप पैनिक को "पकड़ना" और निष्पादन को पुनर्स्थापित करना चाहते हैं, तो defer के साथ recover का उपयोग किया जाता है। यह catch का सबसे करीबी एनालॉग है।
recover का उदाहरण:
func safeCall(f func()) { defer func() { if r := recover(); r != nil { fmt.Pr