Go
गलती संभालना
खोज…
परिचय
गो में, अप्रत्याशित परिस्थितियों को त्रुटियों का उपयोग करके नियंत्रित किया जाता है, अपवादों को नहीं। यह दृष्टिकोण सी के समान है, जावा या अन्य ऑब्जेक्ट-ओरिएंटेड भाषाओं की तुलना में इरनो का उपयोग करते हुए, उनकी कोशिश / कैच ब्लॉक के साथ। हालाँकि, एक त्रुटि पूर्णांक नहीं बल्कि एक अंतरफलक है।
एक फ़ंक्शन जो विफल हो सकता है वह आमतौर पर अंतिम रिटर्न मान के रूप में एक त्रुटि देता है। यदि यह त्रुटि शून्य नहीं है, तो कुछ गलत हो गया है, और फ़ंक्शन के कॉलर को तदनुसार कार्रवाई करनी चाहिए।
टिप्पणियों
ध्यान दें कि कैसे गो में आप एक त्रुटि नहीं बढ़ाते हैं । इसके बजाय, आप विफलता के मामले में एक त्रुटि लौटाते हैं ।
यदि कोई फ़ंक्शन विफल हो सकता है, तो अंतिम लौटा हुआ मूल्य आमतौर पर एक error
प्रकार है।
// This method doesn't fail
func DoSomethingSafe() {
}
// This method can fail
func DoSomething() (error) {
}
// This method can fail and, when it succeeds,
// it returns a string.
func DoAndReturnSomething() (string, error) {
}
त्रुटि मान बनाना
त्रुटि पैकेज बनाने का सबसे सरल तरीका errors
का उपयोग करना है।
errors.New("this is an error")
यदि आप किसी त्रुटि के लिए अतिरिक्त जानकारी जोड़ना चाहते हैं, तो fmt
पैकेज एक उपयोगी त्रुटि निर्माण विधि भी प्रदान करता है:
var f float64
fmt.Errorf("error with some additional information: %g", f)
यहां एक पूर्ण उदाहरण दिया गया है, जहां त्रुटि एक फ़ंक्शन से लौटाई गई है:
package main
import (
"errors"
"fmt"
)
var ErrThreeNotFound = errors.New("error 3 is not found")
func main() {
fmt.Println(DoSomething(1)) // succeeds! returns nil
fmt.Println(DoSomething(2)) // returns a specific error message
fmt.Println(DoSomething(3)) // returns an error variable
fmt.Println(DoSomething(4)) // returns a simple error message
}
func DoSomething(someID int) error {
switch someID {
case 3:
return ErrThreeNotFound
case 2:
return fmt.Errorf("this is an error with extra info: %d", someID)
case 1:
return nil
}
return errors.New("this is an error")
}
एक कस्टम त्रुटि प्रकार बनाना
गो में, एक त्रुटि को किसी भी मूल्य से दर्शाया जाता है जो खुद को स्ट्रिंग के रूप में वर्णित कर सकता है। कोई भी प्रकार जो अंतर्निहित error
इंटरफ़ेस को लागू करता है वह एक त्रुटि है।
// The error interface is represented by a single
// Error() method, that returns a string representation of the error
type error interface {
Error() string
}
निम्न उदाहरण दिखाता है कि स्ट्रिंग कंपोजिट शाब्दिक का उपयोग करके एक नई त्रुटि प्रकार को कैसे परिभाषित किया जाए।
// Define AuthorizationError as composite literal
type AuthorizationError string
// Implement the error interface
// In this case, I simply return the underlying string
func (e AuthorizationError) Error() string {
return string(e)
}
मैं अब त्रुटि के रूप में अपने कस्टम त्रुटि प्रकार का उपयोग कर सकता हूं:
package main
import (
"fmt"
)
// Define AuthorizationError as composite literal
type AuthorizationError string
// Implement the error interface
// In this case, I simply return the underlying string
func (e AuthorizationError) Error() string {
return string(e)
}
func main() {
fmt.Println(DoSomething(1)) // succeeds! returns nil
fmt.Println(DoSomething(2)) // returns an error message
}
func DoSomething(someID int) error {
if someID != 1 {
return AuthorizationError("Action not allowed!")
}
// do something here
// return a nil error if the execution succeeded
return nil
}
कोई त्रुटि लौटा रहा है
गो में आप एक त्रुटि नहीं बढ़ाते हैं । इसके बजाय, आप विफलता के मामले में एक error
लौटाते हैं ।
// This method can fail
func DoSomething() error {
// functionThatReportsOK is a side-effecting function that reports its
// state as a boolean. NOTE: this is not a good practice, so this example
// turns the boolean value into an error. Normally, you'd rewrite this
// function if it is under your control.
if ok := functionThatReportsOK(); !ok {
return errors.New("functionThatReportsSuccess returned a non-ok state")
}
// The method succeeded. You still have to return an error
// to properly obey to the method signature.
// But in this case you return a nil error.
return nil
}
यदि विधि कई मान लौटाता है (और निष्पादन विफल हो सकता है), तो अंतिम तर्क के रूप में त्रुटि को वापस करने के लिए मानक सम्मेलन है।
// This method can fail and, when it succeeds,
// it returns a string.
func DoAndReturnSomething() (string, error) {
if os.Getenv("ERROR") == "1" {
return "", errors.New("The method failed")
}
s := "Success!"
// The method succeeded.
return s, nil
}
result, err := DoAndReturnSomething()
if err != nil {
panic(err)
}
एक त्रुटि को संभालना
गो त्रुटियों में एक फ़ंक्शन कॉल से वापस किया जा सकता है। सम्मेलन यह है कि यदि कोई विधि विफल हो सकती है, तो अंतिम लौटा तर्क एक error
।
func DoAndReturnSomething() (string, error) {
if os.Getenv("ERROR") == "1" {
return "", errors.New("The method failed")
}
// The method succeeded.
return "Success!", nil
}
यदि विधि विफल रही, तो आप जाँच करने के लिए कई चर असाइनमेंट का उपयोग करते हैं।
result, err := DoAndReturnSomething()
if err != nil {
panic(err)
}
// This is executed only if the method didn't return an error
fmt.Println(result)
यदि आप त्रुटि में रुचि नहीं रखते हैं, तो आप इसे _
को असाइन करके इसे अनदेखा कर सकते हैं।
result, _ := DoAndReturnSomething()
fmt.Println(result)
बेशक, त्रुटि की अनदेखी करने के गंभीर प्रभाव हो सकते हैं। इसलिए, यह आमतौर पर अनुशंसित नहीं है।
यदि आपके पास कई विधि कॉल हैं, और श्रृंखला में एक या अधिक विधियाँ एक त्रुटि लौटा सकती हैं, तो आपको उस त्रुटि को पहले स्तर तक प्रचारित करना चाहिए जो इसे संभाल सकती है।
func Foo() error {
return errors.New("I failed!")
}
func Bar() (string, error) {
err := Foo()
if err != nil {
return "", err
}
return "I succeeded", nil
}
func Baz() (string, string, error) {
res, err := Bar()
if err != nil {
return "", "", err
}
return "Foo", "Bar", nil
}
दहशत से उबरना
एक सामान्य गलती यह है कि एक स्लाइस की घोषणा करें और इसे शुरू किए बिना इंडेक्स से अनुरोध करना शुरू करें, जो "इंडेक्स आउट ऑफ रेंज" आतंक की ओर जाता है। निम्नलिखित कोड बताते हैं कि कैसे कार्यक्रम से बाहर निकलने के बिना आतंक से उबरने के लिए, जो एक आतंक के लिए सामान्य व्यवहार है। ज्यादातर स्थितियों में, घबराहट पर कार्यक्रम से बाहर निकलने के बजाय इस फैशन में एक त्रुटि वापस करना केवल विकास या परीक्षण उद्देश्यों के लिए उपयोगी है।
type Foo struct {
Is []int
}
func main() {
fp := &Foo{}
if err := fp.Panic(); err != nil {
fmt.Printf("Error: %v", err)
}
fmt.Println("ok")
}
func (fp *Foo) Panic() (err error) {
defer PanicRecovery(&err)
fp.Is[0] = 5
return nil
}
func PanicRecovery(err *error) {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
//fmt.Println("Panicing")
//panic(r)
*err = r.(error)
} else {
*err = r.(error)
}
}
}
एक अलग फ़ंक्शन (बंद करने के बजाय) का उपयोग अन्य कार्यों में उसी फ़ंक्शन के पुन: उपयोग की अनुमति देता है जो आतंक से ग्रस्त है।