टेक हैंडलिंग तकनीक में त्रुटि [बंद]


108

मैं अभी गो के साथ शुरुआत कर रहा हूं। मेरे कोड में यह बहुत है:

   if err != nil {
      //handle err
   }

या यह

  if err := rows.Scan(&some_column); err != nil {
      //handle err
  }

क्या गो में त्रुटियों की जाँच करने और उन्हें संभालने के लिए कुछ अच्छे मुहावरे / रणनीतियाँ / सर्वोत्तम-प्रथाएँ हैं?

स्पष्ट करने के लिए संपादित करें: मैं पेटिंग या सुझाव नहीं दे रहा हूं कि गो टीम कुछ बेहतर लेकर आए। मैं पूछ रहा हूं कि क्या मैं इसे सही कर रहा हूं या मैंने कुछ तकनीक को याद किया है जो समुदाय के साथ आया था। सबको शुक्रीया।


4
नहीं, वास्तव में नहीं है। यह एक अक्सर चर्चा का विषय है, और एक समझदार है। कई विकास प्रस्ताव भी थे। टीम के जवाब से लगता है कि यह एक अच्छी तरह से लिखित कोड में समस्या नहीं होनी चाहिए।
डेनिज सेग्यूरेट


ध्यान दें कि यह संबंधित प्रश्न वास्तव में इस एक के समान नहीं है। उत्तर भी विशिष्ट हैं।
सेज्यूरेट

इस झुंझलाहट के लिए एक तर्क भी है: यह तेजी से एक कार्यक्रम लिखने के लिए कठिन बनाता है, लेकिन यह भी केवल त्रुटियों को पुनर्जीवित करके बग बनाने के लिए कठिन बनाता है।
डेयस सेग्रुट

आप पा सकते हैं एंड्रयू गेरैंड और ब्रैड फिट्ज़पैट्रिक ने गोवे में HTTP / 2 क्लाइंट की शुरुआत को कम से कम इसी तरह के फैशन youtube.com/watch?v=yG-UaBJXZ80 पर
सुप्रीत सेठी

जवाबों:


61

आपका कोड मुहावरेदार है और मेरी राय में यह उपलब्ध सर्वोत्तम अभ्यास है। कुछ यकीन के लिए असहमत होंगे, लेकिन मैं तर्क दूंगा कि यह गोलंग में सभी मानक पुस्तकालयों में देखी जाने वाली शैली है । दूसरे शब्दों में, गो लेखक इस तरह से एरर हैंडलिंग लिखते हैं।


12
"गो लेखक इस तरह से एरर हैंडलिंग लिखते हैं।" मुझे अच्छा लगता है।
गमोर

"कुछ लोग निश्चित रूप से असहमत होंगे" : मुझे यकीन नहीं है कि कोई कहेगा कि यह आज उपलब्ध सबसे अच्छा अभ्यास नहीं है। कुछ लोग सिंटैक्स शुगर या अन्य परिवर्तन पूछते हैं, लेकिन आज मुझे नहीं लगता कि कोई भी गंभीर कोडर अन्यथा त्रुटियों की जांच करेगा।
सेज्यूरेट

@ डायस्ट्रो: ठीक है, कुछ लोग कहते हैं " यह sux ", अन्य इसे कहते हैं "त्रुटियों को वापसी मूल्यों में संभाला जाता है। 70 OK% शैली।" , और इतने पर ;-)
ZZZZ

2
@jnml हैंडलिंग त्रुटियां इस तरह से भाषा डिजाइन का विषय है, जो एक अत्यधिक विवादास्पद विषय है। सौभाग्य से चुनने के लिए दर्जनों भाषाएं हैं।
फ़ूज

4
बस मुझे मारता है कि हर एक फ़ंक्शन कॉल के लिए समान पैटर्न का उपयोग कैसे किया जाता है। यह कोड को कुछ स्थानों पर शोर करता है और बिना किसी सूचना को खोए कोड को सरल बनाने के लिए सिंटैक्टिक शुगर के लिए चिल्ला रहा है, जो अनिवार्य रूप से संक्षिप्तता की परिभाषा है (जो मेरा मानना ​​है कि क्रिया से बेहतर गुण है, लेकिन यह यकीनन एक विवादास्पद है बिंदु)। सिद्धांत ध्वनि है, लेकिन वाक्यविन्यास वांछित IMHO होने के लिए बहुत कुछ छोड़ देता है। हालाँकि शिकायत करना निषिद्ध है, इसलिए मैं अभी अपनी कुल-सहायता पीऊंगा ;-)
थॉमस

30

इस सवाल के छह महीने बाद रॉब पाइक ने एक ब्लॉग पोस्ट लिखा जिसका शीर्षक Errors are Values ​​है

वहाँ वह तर्क देता है कि आपको ओपी द्वारा प्रस्तुत तरीके से कार्यक्रम करने की आवश्यकता नहीं है, और मानक पुस्तकालय में कई स्थानों का उल्लेख है जहाँ वे एक अलग पैटर्न का उपयोग करते हैं।

बेशक एक सामान्य मूल्य जिसमें त्रुटि मान शामिल है, यह परखना है कि क्या यह शून्य है, लेकिन अनगिनत अन्य चीजें हैं जो एक त्रुटि मान के साथ कर सकते हैं, और उन कुछ अन्य चीजों के आवेदन से आपका कार्यक्रम बेहतर हो सकता है, बॉयलरप्लेट का बहुत कुछ नष्ट करना कि अगर हर त्रुटि बयान के साथ एक रटे के साथ जाँच की जाती है।

...

अपनी त्रुटि से निपटने के लिए भाषा का उपयोग करें।

लेकिन याद रखें: आप जो भी करते हैं, हमेशा अपनी त्रुटियों की जांच करें!

अच्छा पढ़ा है।


धन्यवाद! उस की जाँच करेंगे।
गोरमो

लेख कमाल का है, यह मूल रूप से एक ऐसी वस्तु का परिचय देता है जो विफल स्थिति में हो सकता है, और यदि ऐसा है तो आप बस इसके साथ जो कुछ भी करते हैं उसे अनदेखा कर देंगे और विफल स्थिति में रहेंगे। मेरे लिए लगभग मोनाड जैसा लगता है।
वाटरलिंक

@Waterlink आपका कथन निरर्थक है। जो कुछ भी एक राज्य है वह लगभग-मोनाद है, यदि आप इसे थोड़ा सा भी काटते हैं। मेरी तुलना en.wikipedia.org/wiki/Null_Object_pattern से अधिक उपयोगी है, मुझे लगता है।
user7610

@ user7610, एक प्रतिक्रिया के लिए धन्यवाद। मैं केवल सहमत हो सकता हूं।
वाटरलिंक

2
पाईक: "लेकिन याद रखें: आप जो भी करते हैं, हमेशा अपनी त्रुटियों की जांच करें!" - यह इतना 80 है। त्रुटियां कहीं भी हो सकती हैं, प्रोग्रामर पर बोझ डालना बंद करें और पीट की खातिर अपवादों को अपनाएं।
स्लावोमिर

22

मैं jnml के जवाब से सहमत हूँ कि वे दोनों मुहावरेदार कोड हैं, और निम्नलिखित जोड़ सकते हैं:

आपका पहला उदाहरण:

if err != nil {
      //handle err
}

एक से अधिक रिटर्न वैल्यू से निपटने पर अधिक मुहावरेदार है। उदाहरण के लिए:

val, err := someFunc()
if err != nil {
      //handle err
}
//do stuff with val

आपका दूसरा उदाहरण अच्छा शॉर्टहैंड है जब केवल errमूल्य के साथ काम कर रहा है । यह तब लागू होता है जब फ़ंक्शन केवल एक रिटर्न देता है error, या यदि आप जानबूझकर लौटाए गए मानों को छोड़कर अनदेखा करते हैं error। एक उदाहरण के रूप में, यह कभी कभी के साथ प्रयोग किया जाता है ReaderऔरWriter कार्यों कि एक वापसी intलिखा बाइट्स (कभी कभी अनावश्यक जानकारी) की संख्या की और एक error:

if _, err := f.Read(file); err != nil {
      //handle err
}
//do stuff with f

यदि इनिशियलाइज़ेशन स्टेटमेंट का उपयोग किया जाता है तो दूसरे फॉर्म को संदर्भित किया जाता है ।

इसलिए सर्वोत्तम प्रथाओं के संबंध में, जहां तक ​​मुझे पता है (उपयोग करने के अलावा) जब आपको उनकी आवश्यकता है, तो नई त्रुटियों को बनाने के लिए "त्रुटियों" पैकेज ) आपने बहुत सारी चीजों को कवर किया है जो आपको Go में त्रुटियों को जानने की जरूरत है!

संपादित करें: यदि आप पाते हैं कि आप वास्तव में अपवादों के बिना नहीं रह सकते हैं, तो आप उनके साथ नकल कर सकते हैं defer, panicऔरrecover


4

मैंने गो फ़ंक्शंस की एक कतार के माध्यम से सुव्यवस्थित त्रुटि से निपटने और पाइपिंग के लिए एक पुस्तकालय बनाया।

आप इसे यहाँ पा सकते हैं: https://github.com/go-on/queue

इसमें एक कॉम्पैक्ट और एक वर्बोज़ सिंथैटिक वेरिएंट है। यहाँ लघु वाक्य रचना के लिए एक उदाहरण दिया गया है:

import "github.com/go-on/queue/q"

func SaveUser(w http.ResponseWriter, rq *http.Request) {
    u := &User{}
    err := q.Q(                      
        ioutil.ReadAll, rq.Body,  // read json (returns json and error)
    )(
        // q.V pipes the json from the previous function call
        json.Unmarshal, q.V, u,   // unmarshal json from above  (returns error)
    )(
        u.Validate,               // validate the user (returns error)
    )(
        u.Save,                   // save the user (returns error)
    )(
        ok, w,                    // send the "ok" message (returns no error)
    ).Run()

    if err != nil {
       switch err {
         case *json.SyntaxError:
           ...
       }
    }
}

कृपया ध्यान रखें कि थोड़ा सा प्रदर्शन ओवरहेड है, क्योंकि यह प्रतिबिंब का उपयोग करता है।

इसके अलावा यह मुहावरेदार गो कोड नहीं है, इसलिए आप इसे अपनी परियोजनाओं में उपयोग करना चाहेंगे, या यदि आपकी टीम इसका उपयोग करने पर सहमत है।


3
सिर्फ इसलिए कि आप ऐसा कर सकते हैं, इसका मतलब यह नहीं है कि यह एक अच्छा विचार है। यह उत्तरदायित्व पैटर्न की श्रृंखला जैसा दिखता है , शायद पढ़ने के लिए कठिन (राय) को छोड़कर। मेरा सुझाव है कि यह "मुहावरेदार गो" नहीं है। दिलचस्प है, हालांकि।
स्टीवन सोरोका

2

गोलंग और अन्य भाषाओं में त्रुटियों को संभालने के लिए एक "रणनीति" कॉल स्टैक तक त्रुटियों को लगातार प्रचारित करना है जब तक कि आप उस त्रुटि को संभालने के लिए कॉल स्टैक में पर्याप्त उच्च न हों। यदि आपने उस त्रुटि को बहुत जल्दी संभालने की कोशिश की, तो आप संभवतः दोहराए जाने वाले कोड को समाप्त कर देंगे। यदि आप इसे बहुत देर से संभालते हैं, तो आप अपने कोड में कुछ तोड़ देंगे। गोलंग इस प्रक्रिया को सुपर आसान बनाता है क्योंकि यह सुपर स्पष्ट करता है कि क्या आप किसी दिए गए स्थान पर एक त्रुटि को संभाल रहे हैं या इसे प्रचारित कर रहे हैं।

यदि आप त्रुटि को अनदेखा करने जा रहे हैं, तो एक सरल _ इस तथ्य को बहुत स्पष्ट रूप से प्रकट करेगा। यदि आप इसे संभाल रहे हैं, तो त्रुटि के जिस मामले को आप संभाल रहे हैं, वह बिल्कुल स्पष्ट है, क्योंकि आप इस कथन में इसकी जांच करेंगे।

जैसा कि ऊपर लोगों ने कहा, एक त्रुटि वास्तव में सिर्फ एक सामान्य मूल्य है। यह इसे इस तरह मानता है।


2

Go देवताओं ने Go 2 में त्रुटि से निपटने के लिए "मसौदा डिजाइन" प्रकाशित किया है। इसका उद्देश्य त्रुटियों को बदलना है:

अवलोकन और डिजाइन

वे उपयोगकर्ताओं से प्रतिक्रिया चाहते हैं!

प्रतिक्रिया विकी

संक्षेप में, ऐसा दिखता है:

func f() error {
   handle err { fmt.Println(err); return err }
   check mayFail()
   check canFail()
}

अद्यतन: मसौदे के डिजाइन को बहुत आलोचना मिली है, इसलिए मैंने एक समाधान के लिए संभावनाओं के मेनू के साथ गो 2 त्रुटि हैंडलिंग के लिए विचार करने के लिए आवश्यकताओं का मसौदा तैयार किया ।


1

उद्योग में अधिकांश, मानक नियमों का पालन कर रहे हैं जो गोलंग प्रलेखन त्रुटि हैंडलिंग और गो में उल्लिखित हैं । और यह परियोजना के लिए डॉक्टर निर्माण में भी मदद करता है।


यह अनिवार्य रूप से एक लिंक केवल उत्तर है। मैं आपको सुझाव दूंगा कि आप उत्तर में कुछ सामग्री जोड़ दें ताकि यदि लिंक अमान्य हो जाए, तो भी आपका उत्तर उपयोग में रहेगा।
नव

बहुमूल्य टिप्पणी के लिए धन्यवाद।
psililakanti

0

नीचे गो के लिए त्रुटि से निपटने को कम करने पर मेरा ध्यान है, नमूना तब है जब एचटीटीपी यूआरएल पैरामीटर प्राप्त कर रहा है:

( Https://blog.golang.org/errors-are-values से प्राप्त डिज़ाइन पैटर्न )

type HTTPAdapter struct {
    Error *common.AppError
}

func (adapter *HTTPAdapter) ReadUUID(r *http.Request, param string, possibleError int) uuid.UUID {
    requestUUID := uuid.Parse(mux.Vars(r)[param])
    if requestUUID == nil { 
        adapter.Error = common.NewAppError(fmt.Errorf("parameter %v is not valid", param),
            possibleError, http.StatusBadRequest)
    }
    return requestUUID
}

कई संभावित मापदंडों के लिए इसे कॉल करना निम्नानुसार होगा:

    adapter := &httphelper.HTTPAdapter{}
    viewingID := adapter.ReadUUID(r, "viewingID", common.ErrorWhenReadingViewingID)
    messageID := adapter.ReadUUID(r, "messageID", common.ErrorWhenReadingMessadeID)
    if adapter.Error != nil {
        return nil, adapter.Error
    }

यह एक चांदी की गोली नहीं है, नकारात्मक पक्ष यह है कि यदि आपके पास कई त्रुटियां थीं तो आप केवल अंतिम त्रुटि प्राप्त करने में सक्षम हैं।

लेकिन इस उदाहरण में यह अपेक्षाकृत दोहराव और कम जोखिम है, इसलिए मुझे केवल अंतिम संभव त्रुटि मिल सकती है।


-1

आप कर सकते हैं इसी तरह की त्रुटियों के लिए अपने त्रुटि हैंडलिंग कोड साफ हैं (चूंकि त्रुटियाँ मान हैं जिन्हें आपको यहां सावधान रहना होगा) और एक फ़ंक्शन लिखें जिसे आप त्रुटि को संभालने के लिए पारित त्रुटि के साथ कहते हैं। आपको हर बार तब "if इरेट! = Nil {}" लिखना नहीं होगा। फिर, यह केवल कोड को साफ करने में परिणाम देगा, लेकिन मुझे नहीं लगता कि यह चीजों को करने का मुहावरेदार तरीका है।

फिर, सिर्फ इसलिए कि आप कर सकते हैं इसका मतलब यह नहीं कि आप ऐसा करना चाहिए


-1

goerr कार्यों के साथ त्रुटियों को संभालने की अनुमति देता है

package main

import "github.com/goerr/goerr"
import "fmt"

func ok(err error) {
    if err != nil {
        goerr.Return(err)
        // returns the error from do_somethingN() to main()
        // sequence() is terminated
    }
}

func sequence() error {
    ok(do_something1())
    ok(do_something2())
    ok(do_something3())

    return nil /// 1,2,3 succeeded
}
func do_something1() error { return nil }
func do_something2() error { return fmt.Errorf("2") }
func do_something3() error {
    fmt.Println("DOING 3")
    return nil
}

func main() {
    err_do_something := goerr.OR1(sequence)

    // handle errors

    fmt.Println(err_do_something)
}

Ick। इस तरह से तर्क से निपटने में त्रुटि की शिकायत करना / छुपाना एक अच्छा विचार नहीं है। परिणामी कोड (जिसे goerr द्वारा स्रोत पूर्व-प्रसंस्करण की आवश्यकता है) मुहावरेदार गो कोड की तुलना में पढ़ने / कारण के लिए कठिन है।
डेव सी

-4

यदि आप त्रुटियों का सटीक नियंत्रण चाहते हैं, तो यह समाधान नहीं हो सकता है, लेकिन मेरे लिए, अधिकांश समय, कोई भी त्रुटि शो स्टॉपर है।

इसलिए, मैं इसके बजाय फ़ंक्शन का उपयोग करता हूं।

func Err(err error) {
    if err!=nil {
        fmt.Println("Oops", err)
        os.Exit(1)
    }
}

fi, err := os.Open("mmm.txt")
Err(err)

इस तरह के संदेशों के stderrबजाय जाना चाहिए stdout, इसलिए बस का उपयोग करें log.Fatal(err)या log.Fatalln("some message:", err)। चूँकि लगभग mainपूरे कार्यक्रम को समाप्त करने के लिए इस तरह का निर्णय लेने के अलावा और कुछ नहीं करना चाहिए (अर्थात कार्यों / विधियों से त्रुटियों को वापस करें, गर्भपात न करें) यह दुर्लभ स्थिति में आप इसे साफ और बेहतर तरीके से करना चाहते हैं (अर्थात if err := someFunc(); err != nil { log.Fatal(err) }) के बजाय एक "सहायक" फ़ंक्शन के माध्यम से यह स्पष्ट नहीं है कि यह क्या कर रहा है (नाम "Err" अच्छा नहीं है, यह कोई संकेत नहीं देता है कि यह कार्यक्रम को समाप्त कर सकता है)।
डेव सी

नई बात सीखी! धन्यवाद @DaveC
गॉन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.