1 पॉइंट द्वारा GN⁺ 2025-06-04 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Go में if err!= nil की दोहराव वाली pattern वर्षों से user surveys में बड़ी शिकायत बनी रही है, लेकिन Go टीम ने फिलहाल error handling syntax में बदलाव आगे न बढ़ाने का फैसला किया है
  • 2018 में check/handle, 2019 में try, और 2024 में ? proposals—इनमें से किसी पर भी पर्याप्त सहमति नहीं बन सकी; खासकर try को hidden control flow के कारण कड़ा विरोध झेलना पड़ा
  • Go proposal process के अनुसार, अगर सामान्य सहमति नहीं होती तो proposal आम तौर पर reject कर दिया जाता है, और Google की Go टीम के वरिष्ठ सदस्यों के बीच भी अभी सबसे अच्छी दिशा पर सर्वसम्मति नहीं है
  • यथास्थिति बनाए रखने वालों का मानना है कि Go के पास पहले से काम करने वाला error handling तरीका है, और नया syntax code style, debugging, documentation, tools और मौजूदा code पर बड़ा cost डालता है
  • Go टीम error handling syntax को मुख्य लक्ष्य बनाने वाले खुले proposals और नए proposals को अतिरिक्त जांच के बिना बंद करेगी, और जब तक समस्या की समझ अधिक स्पष्ट नहीं होती, अन्य सुधार अवसरों पर ध्यान देगी

if err != nil से बनी पुरानी शिकायत

  • Go में सबसे लंबे समय से चली आ रही शिकायतों में से एक error handling code की लंबाई और verbosity है
  • प्रतिनिधि pattern इस रूप में होता है
x, err := call()
if err != nil {
    // handle err
}
  • जिन programs में API calls अधिक होती हैं और errors को बस return किया जाता है, उनमें if err != nil code के बाकी हिस्से पर हावी हो सकता है
  • उदाहरण function printSum में function body की 10 lines में से actual काम जैसी दिखने वाली lines calls, output और return मिलाकर 4 हैं, और बाकी 6 lines noise जैसी लगती हैं
  • Go के वार्षिक user survey में error handling वर्षों तक शीर्ष शिकायत रही; कुछ समय तक generics की कमी इससे आगे रही, लेकिन Go में generics support आने के बाद error handling फिर से शीर्ष शिकायत बन गई

syntax के तीन मुख्य proposals

  • Go टीम की पहली स्पष्ट कोशिश 2018 में Go 2 effort के हिस्से के रूप में शुरू हुई, जब Russ Cox ने समस्या को आधिकारिक रूप से व्यवस्थित किया
  • Marcel van Lohuizen का draft design check और handle mechanisms पर आधारित था, और इसमें अन्य भाषाओं के approaches और alternatives का विश्लेषण भी शामिल था
func printSum(a, b string) error {
    handle err { return err }
    x := check strconv.Atoi(a)
    y := check strconv.Atoi(b)
    fmt.Println("result:", x + y)
    return nil
}
  • check/handle approach को बहुत जटिल माना गया, और 2019 में एक ज्यादा सरल try proposal आया
    • check जैसा keyword try built-in function बन गया
    • handle वाला हिस्सा हटा दिया गया
    • मौजूदा error handling code को try style में बदलने के लिए tryhard tool बनाया गया
    • संबंधित GitHub issue पर करीब 900 comments के साथ तीखी चर्चा हुई
func printSum(a, b string) error {
    // use a defer statement to augment errors before returning
    x := try(strconv.Atoi(a))
    y := try(strconv.Atoi(b))
    fmt.Println("result:", x + y)
    return nil
}
  • try error आने पर enclosing function से return करके control flow को प्रभावित करता था, और deeply nested expressions के अंदर भी return हो सकता था, इसलिए कई users के लिए इसे स्वीकार करना कठिन था
  • उस समय नया keyword लाना बेहतर हो सकता था, और अब go.mod files और per-file directives से language version को बारीकी से control किया जा सकता है
  • Jimmy Frasche का हालिया proposal मूल check/handle design पर लौटते हुए उसकी कुछ कमियों को address करने की दिशा अपनाता है

try के बाद process पर पुनर्विचार और ? proposal

  • try proposal के बाद Russ Cox ने “Thinking about the Go Proposal Process” series के जरिए proposal process पर पुनर्विचार किया
  • “Go Proposal Process: Large Changes” ने आकलन किया कि try implementation schedule के साथ proposal नहीं, बल्कि दूसरा draft design होना चाहिए था
  • इसके बाद कई वर्षों तक Go टीम ने error handling syntax changes को आगे नहीं बढ़ाया, और community से मिलते-जुलते, रोचक, समझने में कठिन या अव्यावहारिक proposals लगातार आते रहे
  • Ian Lance Taylor ने error handling improvement proposals की स्थिति को व्यवस्थित करने के लिए एक umbrella issue बनाया, और संबंधित feedback व discussions इकट्ठा करने के लिए Go Wiki भी बना
  • Sean K. H. Liao का “go error handling proposals” वर्षों के कई error handling proposals को track करता है
  • शिकायतें जारी रहने पर Ian Lance Taylor ने 2024 में ? का उपयोग करके error handling boilerplate घटाने वाला proposal प्रकाशित किया
    • यह Rust के ? operator से उधार लिया गया notation था
    • एक छोटे informal user study में अधिकांश participants ने ? का उपयोग करने वाले Go code का अर्थ सही अनुमान लगाया
    • सामान्य Go code को नए syntax में बदलने वाला tool और compiler prototype भी बनाया गया
func printSum(a, b string) error {
    x := strconv.Atoi(a) ?
    y := strconv.Atoi(b) ?
    fmt.Println("result:", x + y)
    return nil
}
  • यह proposal भी जल्द ही बहुत सारे comments और preference-based detailed modification proposals से भर गया, और Ian ने proposal बंद करके सामग्री को discussion में स्थानांतरित कर दिया
  • थोड़ा संशोधित version को कुछ अधिक सकारात्मक प्रतिक्रिया मिली, लेकिन व्यापक support नहीं मिला

अभी रुकने की वजह

  • Go टीम ने तय किया है कि निकट भविष्य में error handling की syntax problem को हल करने की कोशिश रोक देनी चाहिए
  • proposal process इस निर्णय का समर्थन करता है
    • proposal process का लक्ष्य समय पर outcome पर सामान्य सहमति तक पहुंचना है
    • issue tracker discussion में सामान्य सहमति न मिलने पर आम तौर पर proposal reject कर दिया जाता है
    • अगर सहमति या अगला कदम नहीं मिलता, तो Go architects discussion की समीक्षा करते हैं और internal consensus की कोशिश करते हैं
  • किसी भी error handling proposal को consensus के करीब support नहीं मिला, और सभी reject हुए
  • Google की Go टीम के senior members भी अभी आगे बढ़ने की सबसे अच्छी दिशा पर unanimous नहीं हैं, और मजबूत सहमति के बिना तर्कसंगत रूप से आगे बढ़ना संभव नहीं है

यथास्थिति और बदलाव के तर्क

  • यथास्थिति बनाए रखने के पक्ष में Go की maturity और ecosystem cost जैसे व्यावहारिक कारण हैं
    • अगर Go ने शुरुआती दौर में error handling के लिए dedicated syntax sugar जोड़ा होता, तो आज विवाद कम होता; लेकिन Go को 15 साल हो चुके हैं और इसके पास पहले से काम करने वाला error handling तरीका है
    • अभी कोई perfect solution मिल भी जाए, तो स्थिति ऐसी हो सकती है कि बदलाव समर्थकों के बजाय यथास्थिति पसंद करने वाले असंतुष्ट हो जाएं
    • generics को users को अनिवार्य रूप से सीधे इस्तेमाल करना जरूरी नहीं है, लेकिन नया error handling syntax न इस्तेमाल करने पर code unidiomatic दिख सकता है, इसलिए व्यवहार में अधिकांश लोगों को इसे अपनाना पड़ेगा
    • एक ही काम करने के कई तरीके न देने वाले Go design rule से भी नया syntax जोड़ना टकरा सकता है
  • := short variable declaration की redeclaring capability error handling के कारण बनी समस्या हल करने के लिए लाई गई थी
    • redeclaration न होती तो लगातार error checks में अलग-अलग err names या अलग variable declarations की जरूरत पड़ती
    • अगर उस समय error handling के लिए बेहतर syntax support होता, तो redeclaration rules और उससे जुड़ी complexity की जरूरत नहीं रही होती
  • errors को ठीक से augment करके handle करने पर सरल repetition का हिस्सा घट जाता है
    • user surveys में errors में stack trace न होने की recurring राय आती है
    • helper functions से augmented errors बनाकर return करना संभव है
    • fmt.Errorf("invalid integer: %q", a) की तरह input value की जानकारी जोड़ने से boilerplate का relative share छोटा हो जाता है
  • standard library features भी error handling boilerplate घटा सकते हैं
    • यह Rob Pike के “Errors are values” जैसी दिशा है
    • कुछ cases में cmp.Or से कई errors को एक साथ handle किया जा सकता है
  • लिखना, पढ़ना और debugging अलग-अलग activities हैं
    • repeated error checks लिखना tedious है, लेकिन IDE और LLM-assisted code completion basic error checks आसानी से generate कर सकते हैं
    • पढ़ते समय verbosity ज्यादा उभरकर दिखती है, और IDE error handling code छिपाने का toggle दे सकता है
    • debugging के दौरान पहले से अलग if statement हो तो println जोड़ना या breakpoint set करना आसान है
    • अगर check, try, ? के पीछे error handling छिप जाए, तो आम तौर पर उसे फिर if statement में वापस बदलना पड़ सकता है, और यह process debugging को जटिल बना सकता है या subtle bugs पैदा कर सकता है
  • language changes में design और implementation के अलावा existing code changes, documentation updates और tools adjustments की cost भी आती है
    • Go टीम अपेक्षाकृत छोटी है, और उसके पास handle करने के लिए कई अन्य priorities भी हैं
    • priorities और team size बदल सकते हैं
  • Google Cloud Next 2025 में Go टीम से मिले कुछ Go users ने जोर देकर कहा कि बेहतर error handling के लिए language नहीं बदलनी चाहिए
    • उनका कहना था कि दूसरी languages से Go में आते समय dedicated error handling syntax की कमी सबसे ज्यादा ध्यान खींचती है, लेकिन ज्यादा idiomatic Go code लिखने लगने पर यह कम महत्वपूर्ण हो जाती है
    • यह sample representative होने के लिए पर्याप्त बड़ा नहीं है, लेकिन GitHub पर दिखने वाले लोगों से अलग समूह हो सकता है
  • बदलाव के समर्थन वाले तर्क भी अब भी valid हैं
    • बेहतर error handling support की कमी user surveys में शीर्ष शिकायत बनी हुई है
    • सिर्फ character count घटाने पर केंद्रित approach गलत दिशा हो सकती है
    • basic error handling को keyword के रूप में साफ दिखाई देने वाला बनाते हुए err != nil boilerplate हटाया जाए, तो code review में error handling हुई है या नहीं, यह जांचना आसान हो सकता है
    • समस्या का मूल कारण सिर्फ syntax की verbosity है या API और developers/end users के लिए meaningful errors बनाने वाली अच्छी error handling की verbosity—यह अभी पर्याप्त रूप से पता नहीं है

Go टीम का निर्णय

  • अब तक error handling को address करने की कोई भी कोशिश पर्याप्त momentum हासिल नहीं कर सकी
  • Go टीम का मानना है कि problem की shared understanding कम है, और इस बात पर भी सभी सहमत नहीं हैं कि समस्या है या नहीं
  • निकट भविष्य में error handling के लिए syntactic language changes आगे नहीं बढ़ाए जाएंगे
  • error handling syntax को मुख्य लक्ष्य बनाने वाले खुले proposals और भविष्य में आने वाले proposals को अतिरिक्त जांच के बिना बंद किया जाएगा
  • community की exploration और discussion error handling syntax change तक नहीं पहुंची, लेकिन इससे Go language और process में कई सुधार हुए

1 टिप्पणियां

 
GN⁺ 2025-06-04
Hacker News पर रायें
  • अगर Go टीम को “ऐसा कर लेते तो हो जाता” वाली शैली के सुझाव हल्के में फेंकने हों, तो पहले लेख में लिंक किए गए Wiki पेज https://go.dev/wiki/Go2ErrorHandlingFeedback और GitHub issue search https://github.com/golang/go/issues?q=+is%3Aissue+label%3Aerror-handling देख लेना चाहिए
    आप जो सुझाव देने जा रहे हैं, वह लगभग निश्चित तौर पर पहली बार नहीं आया होगा, और उनमें से कई पर पहले ही गहराई से विचार हो चुका होने की संभावना है
    Go टीम के इस ईमानदार approach को मैं अच्छा मानता/मानती हूँ, और अब भी काम में रोज़ Go का आनंद से इस्तेमाल करता/करती हूँ

    • जिस design draft पर feedback आधारित था, उसमें C++, Rust, Swift का ज़िक्र है, लेकिन लिंक किए गए विशाल feedback document में Haskell/Scala/OCaml में इस्तेमाल होने वाली do notation, for-comprehension, monadic-let जैसी approaches नहीं मिलीं
      सबसे ज़्यादा comments वाले GitHub issues के कुछ pages में भी वैसा कुछ नहीं दिखा, और सिर्फ़ यह मान लेना मुश्किल है कि Go टीम language design की जादूगर है, इसलिए यहाँ लोग जो हल्के-फुल्के solutions डाल रहे हैं उन्हें उन्होंने ज़रूर देखा होगा
      Go टीम ने Java जैसी गलती की—यानी static typing होते हुए भी parametric polymorphism न होना—और इस error handling समस्या की जड़ भी वहीं है, लेकिन वे हाथ खड़े करके इसे ठीक न करने जैसे दिखते हैं
    • यह हैरानी की बात है कि सचमुच बहुत smart और अनुभवी लोगों ने वह page लिखा और सालों तक चर्चा की, फिर भी Haskell-style solution, यानी Maybe/Either monad और bind operator वाली do notation, कहीं दिखाई नहीं देती
      यह बड़ा और डरावना लग सकता है, लेकिन errors को उस जगह तक propagate करने का, जहाँ उन्हें handle किया जा सके, और फिर भी उन्हें भुलाया न जाने देने का यह एक elegant और functionally pure तरीका है
      Haskell code लिखने वालों के लिए यह इतना गहराई से रचा-बसा तरीका है कि समझ नहीं आता Go community में कोई ऐसा नहीं था जो इसे जानता और पसंद करता हो
      page और links के लिए धन्यवाद, लेकिन जो लोग अपनी language की इतनी परवाह करते हैं, उनका इतने well-established solution को छोड़ देना उलझन भरा लगता है
    • शायद इसका जवाब कहीं पहले से होगा, लेकिन जानना चाहता/चाहती हूँ कि यह सिर्फ़ Go में ही खास तौर पर कठिन समस्या क्यों है
      लगभग हर language के पास अपना बेहतर तरीका है; क्या बात सिर्फ़ इतनी है कि फैसला नहीं हो पा रहा या सबको संतुष्ट नहीं किया जा सकता, या Go language में ही कोई ठोस वजह है कि दूसरी languages के solutions फिट नहीं बैठते?
    • Go की आलोचना में अक्सर दिखने वाला pattern यह है कि अपेक्षाकृत amateur लोग यह मान लेते हैं कि Go बनाने वाले लोग programming languages के बारे में उनसे कम जानते हैं
      असल में लगभग हर मामले में वे कहीं ज़्यादा जानते हैं
      amateur लोग भोलेपन से सोचते हैं कि जिस language में सबसे ज़्यादा features ठूँस दिए गए हों वही सबसे अच्छी है, खासकर अगर उसमें उनकी पसंद का feature आ जाए
      यह कुछ वैसा है जैसे चाकू बनाना अभी-अभी सीखने वाला व्यक्ति Japanese chef knife देखकर उसे अधूरा समझे, और सोचे कि finger grooves, secret compartment, lighter और Bluetooth speaker वाला 3D-printed handle लगा दें तो वह बेहतर हो जाएगा
    • अब जबकि edit करने के लिए approval लेना पड़ता है, फिर भी इसे Wiki कहना अजीब है
  • checkbox list बना लें, हर item पर चर्चा करके उसे भरें, और जब तक कोई घातक semantic error या soundness hole न मिले, उसे फिर से न हटाएँ
    जब सब भर जाए तो implement कर दें, और .await इस्तेमाल हो या /await या .await!()—इस पर शोर मचाने वाले लोग फिर गायब हो जाएँगे
    Rust ऐसे ही चलता है; कुछ issues 10 साल से ज़्यादा भी अटकते हैं, लेकिन आखिरकार items भरते हैं और latest nightly से stable हो जाते हैं
    अगर Go ऐसी single समस्या को, जिससे लगभग हर कोई तुरंत टकराता है, जबकि कई polished proposals मौजूद हैं, उनमें से एक न चुन पाने और bikeshedding रुकने का इंतज़ार करते रहने की वजह से हल नहीं कर पाता, तो वह process एक comedy है

    • “कई complete और perfect proposals मौजूद हैं” जैसी कोई चीज़ नहीं होती
    • यही वह तरीका है जिससे Rust को committee-style design के कारण पढ़ने में बदसूरत और syntax में inconsistent language होने की reputation मिलती है
    • programming language एक designed system होती है, इसलिए उसे समग्र रूप से coherent होना चाहिए
      यह सिर्फ़ features का ऐसा संग्रह नहीं है जो checkbox requirements पूरी हों तो जोड़ दिया जाए
    • 25 साल बाद का reminder लगाना चाहता/चाहती हूँ
      क्या Rust C++ की तरह messy हो गया होगा? क्या Go release के समय जैसा timeless language बना रहेगा?
    • “Go ऐसी single समस्या हल नहीं कर पा रहा जिससे हर कोई तुरंत गुजरता है” कहना अजीब है
      survey में error handling का ज़िक्र करने वालों का अनुपात 13% था, और कुछ लोग मौजूदा तरीके को ही पसंद करते हैं
      https://go.dev/blog/survey2024-h1-results
  • पहले कभी मैंने एक अजीब-सा Go फ़ंक्शन लिखा था, जिसमें उम्मीद थी कि अंदर वाला फ़ंक्शन error लौटाएगा
    इसलिए अगर अंदर वाला फ़ंक्शन error नहीं लौटाता, तो बाहर वाले फ़ंक्शन को error लौटाना और कुछ और संभालना पड़ता था; और अगर अंदर वाला फ़ंक्शन error लौटाता, तो nil लौटाना होता था
    संक्षेप में, if err != nil { ... } नहीं बल्कि if err == nil { // return an error } लिखना था, लेकिन आदतन मैंने पहला वाला लिख दिया और debugging में काफ़ी समय लग गया
    क्योंकि मैं if err != nil को लेकर इतना सुन्न हो चुका था कि दिमाग़ ने इस संभावना पर विचार ही नहीं किया कि वह statement वहाँ नहीं होना चाहिए
    इसलिए मुझे लगता है कि आम expressions के लिए syntactic sugar चाहिए। बहुत आम if err != nil और दुर्लभ if err == nil के बीच फर्क अगर ज़्यादा उभरकर दिखता, तो सच में मदद मिलती

    • हर बार if err == nil लिखते समय मैं // inverted comment लगाता हूँ ताकि वह नज़र आए
      अच्छा होगा अगर भाषा के स्तर पर इसे संभाला जाए, लेकिन कम-से-कम इसे ज़्यादा दिखाई देने लायक बनाने का तरीका साझा कर रहा हूँ
    • बेशक if fruit != "Apple" { ... } भी बिल्कुल वही स्थिति बना सकता है
      जानना चाहूँगा कि इसे सुधारने का कोई सामान्य हल है या नहीं, और इसे सिर्फ़ error handling की समस्या मानना थोड़ा गलत दिशा में लगता है
      errors में कुछ खास या अनोखा नहीं है; वे बाकी चीज़ों जैसी ही एक state हैं
    • यह तो उल्टा syntax बदलने के खिलाफ़ तर्क बनता है
      अगर आम if err == nil { return ... } pattern बन गया, तो इस बार वही code में हर जगह बिखरा होगा
      मौजूदा समाधान ठीक है, और लगता है कि इसे ज़्यादातर वे लोग नापसंद करते हैं जिन्होंने अभी-अभी Go शुरू किया है या जो beginner हैं
      मेरे आसपास लोग explicit, साफ़ और पढ़ने में आसान “verbose” error handling पसंद करते हैं
    • devil's advocate के तौर पर कहूँ तो, IDE और fonts Go syntax mode में ही if err != nil को एक single छोटे ligature symbol की तरह highlight कर सकते हैं या background में धुंधला render कर सकते हैं
      तब if err == nil जैसी, ठीक उस string से अलग कोई भी form उल्टा ज़्यादा नज़र आएगी
    • अच्छा point है। editor में if err … { जैसी folded notation से भी यह हल होता दिखता है
  • मुझे Go की explicit error handling पसंद है
    कोई फ़ंक्शन या तो हमेशा सफल होता है, या सफल या असफल हो सकता है। जो फ़ंक्शन हमेशा सफल होता है वह simple है, और जो फ़ंक्शन fail हो सकता है, अगर वह fail हो जाए तो बाहरी code failed state में आगे नहीं बढ़ सकता, इसलिए उसे handle करना पड़ता है
    यहीं languages अलग-अलग रास्ते लेती हैं। कई languages exceptions throw करती हैं, उन्हें ऊपर उठाती रहती हैं जब तक कोई explicit रूप से catch न करे, और एक तरह का stack trace देती हैं
    Go में मुझे यह पसंद है कि code लिखते समय आपके पास हमेशा चुनने के विकल्प होते हैं: error को ignore करके आगे बढ़ना (foo, _ := doSomething()), meaningful जानकारी के बिना early return करना (return nil, err), उपयोगी context जोड़कर early return करना, या मिले हुए error को interpret करके branch करना
    उदाहरण के लिए, अगर database में modify करने के लिए row न मिले, तो service layer not found error लौटा सकती है और API में वह 404 बन सकता है, या कोई idempotent delete function not found को success के रूप में interpret कर सकता है
    Go 2 या किसी दूसरी language में, nil-able tuple के बजाय Rust/Swift-स्टाइल Result type, और हमेशा सीधे error इस्तेमाल करने के बजाय बेहतर typed और enumerable error types होना अच्छा होगा
    हालांकि Go 1 के idiomatic tuple return के ऊपर Result जोड़ने से एक ही काम करने के कई तरीके बनेंगे, जिससे confusion और fragmentation होगा; इसलिए यह Go 2 या नई language के लिए ज़्यादा उपयुक्त है

    • मेरा अनुभव है कि error handling policy caller को delegate की जानी चाहिए
      stack की lower layers आम तौर पर नहीं जानतीं कि क्या करना चाहिए, इसलिए उन्हें error handle नहीं करना चाहिए
      error handle करने की policy आखिर में अक्सर error को wrap करके stack के ऊपर फिर से return करने की policy बन जाती है, और यह काफी tedious काम बन जाता है
    • “अगर function fail होता है तो उस failure को handle करना चाहिए” — Go ठीक यहीं fail करता है
      Go आपको errors को पूरी तरह ignore करने देता है, और नतीजा crash तक जा सकता है
      robust software बनाने की requirements को सही-सही पहचानने के बाद भी Go की error handling पसंद है, यह मुझे थोड़ा समझ नहीं आता
    • काश borgo[1] syntax ज्यों का त्यों Go 2 language बन जाए। सपने तो देखे जा सकते हैं
      [1]: https://borgo-lang.github.io/ | https://github.com/borgo-lang/borgo
    • इस रफ्तार से तो Go2 कभी रिलीज़ न होने वाली ideas laboratory जैसा लगता है
    • पूछना चाहूँगा कि किससे तुलना करके यह अच्छा है
      सभी functional languages, Rust जैसी कई modern languages, यहाँ तक कि checked exceptions वाला Java भी यह देता है
      generics वाली language में Go-style “error handling” को आम तौर पर replicate किया जा सकता है, और शायद उससे बेहतर code निकलेगा
      अगर जवाब JavaScript या Python है, तो वह आम comparison pattern तो है
  • Go के लिए यह सही फैसला है। जब पहली बार Go से परिचय हुआ था, तो error handling पसंद नहीं थी, लेकिन अब सच में पसंद आने लगी है
    बदलाव की वजह दो चीज़ें थीं। https://go.dev/blog/errors-are-values article पढ़कर “errors are values” वाला नजरिया ठीक से अपनाया, और उसी आधार पर कुछ हद तक लोकप्रिय package https://github.com/stytchauth/sqx भी बनाया
    साथ ही, सचमुच बेतुकी invalid states के लिए panic(err) थोड़ा-थोड़ा इस्तेमाल करने का आदी हो गया हूँ
    ऐसी अटपटी states जिन्हें parent code के पास handle करने की समझ भी नहीं है, उन्हें ज़बरदस्ती हर जगह handle करवाने की जरूरत नहीं; सही जगह लगाए गए एक-दो panic codebase की सैकड़ों error checks हटा सकते हैं
    उदाहरण के लिए, ctx में default logger है या नहीं, जैसी समस्या सोच सकते हैं

    • दुख की बात है। दिए गए दोनों आधारों का इससे कोई संबंध नहीं कि Go error handling कितनी खराब है, और error handling को बेहतर बनाने से वह खराब भी नहीं होगी
      बल्कि सुधार होने की संभावना ज़्यादा है
    • PHP तक में error levels और call site पर errors को suppress करने वाले @ operator की वजह से बेहतर error handling है
      bash में भी -e है
    • मुझे भी Go का तरीका पसंद है। अगर मुझे ज़्यादा निश्चित रूप से पता चल सके कि क्या हो रहा है, तो मैं ज़्यादा code lines स्वीकार कर लूँगा
      पहले जब C# इस्तेमाल करना शुरू किया था, तो try/catch/finally flow, using, nesting, catch में error आ जाए तो क्या होता है, finally में आ जाए तो क्या होता है—यह सब समझना मुझे smart लगता था
      अब बेहतर लगता है कि ऐसी चीज़ों के बारे में न सोचना पड़े
    • Rust-style sum type errors भी values हैं
  • मुझे यह बात पसंद नहीं कि यह लेख Go में error handling की मुख्य समस्या को syntax के बहुत verbose होने के रूप में पेश करता है। मुझे उससे खास फर्क नहीं पड़ता
    ज्यादा अहम बात यह है कि errors चुपचाप फेंके जा सकते हैं या गलती से ignore हो सकते हैं, function call का result कोई value नहीं होता जिसे आसानी से store या pass किया जा सके, और errors.Is की जरूरत पड़ती है; साथ ही पूरा “nested” error वाला मामला type system से अच्छी तरह मेल नहीं खाने वाला एक अजीब runtime mechanism है
    errors पर switch करना भी मुश्किल है, standard library sentinel values इस्तेमाल करती है, और generics के साथ interaction अच्छा नहीं है, इसलिए errgroup जैसे packages की जरूरत पड़ती है
    क्या मैंने कुछ और छोड़ दिया?

    • Go में professional तौर पर काम करने के समय का 90% हर error return branch को statement coverage से cover करने के लिए test cases जबरन बनाने में जाता है
      exceptions वाली language होती तो कोई ऐसा नहीं करता
    • मुझे नहीं लगता कि इस लेख में कहीं भी यह दावा है कि “मुख्य समस्या syntax का बहुत verbose होना है”
      निकट भविष्य में error handling syntax बदलने की कोशिशें आगे नहीं बढ़ाने का फैसला किया गया है, और इससे errors हों या दूसरे विषय, अन्य समस्याओं पर ध्यान देने की जगह बनती है
    • याद रखना चाहिए कि Go को किसी भी रूप में generics support करने में भी बेहद लंबा समय लगा था
      Go का evolution ग्लेशियर जितना धीमा है, और बहुतों के लिए यह bug नहीं बल्कि feature है
    • 100% सहमत। दोनों Googler हैं, फिर भी Go team से फिर निराश होना बहुत अफसोसजनक है
    • पहले point से सहमत हूं, लेकिन errcheck जैसे development tools से इसे कुछ हद तक कम किया जा सकता है: https://github.com/kisielk/errcheck?tab=readme-ov-file
  • “Errors में stack trace नहीं होने” वाली survey feedback को इस तरह समझाना हास्यास्पद है कि helper function enriched error बनाकर return कर दे तो समस्या हल हो सकती है
    if err != nil { return fmt.Errorf("invalid integer: %q", a) } की तरह stack trace manually देना को “error handling” कहना मजेदार है
    Go team की definition के हिसाब से तो exceptions errors को automatically handle कर देती हैं। बेशक C++ को छोड़कर बाकी languages में

    • मजेदार है कि लोग स्क्रीन भर stack trace देखकर उसे clear और useful कहते हैं
      हो सकता है, लेकिन क्या सच में वह सब चाहिए? log cost का क्या?
      frameworks और runtime noise काट देने वाला एक-line wrapped error मुझे कहीं बेहतर लगता है
      अच्छी तरह wrap किया जाए तो search करना भी बहुत आसान होता है, और आमतौर पर stack trace से ज्यादा प्रभावी ढंग से trace किया जा सकता है
      10 साल से ज्यादा full-time Go इस्तेमाल करते हुए मुझे कभी runtime functions या call stack के verbose शोर की जरूरत नहीं पड़ी
  • Elixir developer के नजरिए से यह पागलपन जैसा दिखता है
    Erlang/Elixir में आमतौर पर functions {:ok, result} या {:error, description_or_struct} tuple return करके यह हल कर लेते हैं
    इसके साथ Elixir का with statement इस्तेमाल करें तो error handling को नीचे इकट्ठा किया जा सकता है, जिससे पढ़ना काफी बेहतर हो जाता है
    Go भी with clause जैसा कुछ जोड़ सकता है, ताकि जब तक error nil हो functions चलते रहें और नीचे error handling clause रखा जाए

    • उपलब्ध evidence के आधार पर Go के with statement अपनाने की कोई संभावना नहीं दिखती
      दिलचस्प है कि Go generics, error handling, package management जैसी basic और साफ तौर पर valuable structures को community consensus की कमी के कारण बहुत लंबे समय तक टालता है
      generics को open source release के बाद 13 साल लगे, 16 साल बाद भी error handling नहीं है, और package management में करीब 9 साल लगे
      विचार-विमर्श की value है, लेकिन release करने की भी value है। GitHub comments के 900 comments लिखने वाले लोग आखिर Go ही इस्तेमाल करते रहेंगे, और language में कुछ शामिल कर देना शायद लगातार टालते रहने से बेहतर होता
    • Go का multiple return खुद मेरे नजरिए से अजीब है
      multiple return types वाले function के साथ variables में assign करने के अलावा कुछ खास किया ही नहीं जा सकता
    • Haskell users और Rust fans sum types को अपनी चीज मानते हैं, और लोग उनके comments व लेख पढ़कर उन पर भरोसा करने के बाद डरावने Hindley-Milner rabbit hole में नहीं फंसना चाहते, इसलिए sum types से कतराने लगते हैं
      लेकिन Erlang और Elixir में यह बिना किसी बोझ के पूरी तरह idiomatic तरीका है
      असल में यह ML family से कहीं ज्यादा powerful भी है, क्योंकि वहां sum types open होते हैं
  • मैंने इस चर्चा को बहुत बारीकी से फॉलो नहीं किया है, लेकिन समझ नहीं आता कि Rust वाला तरीका सीधे क्यों नहीं अपनाते
    Go में generics आने के बाद मैं भी तुरंत यही pattern जोड़ता हूं
    लिंक किए गए लेख में बस यह explanation दिखती है कि “Rust में handle के बराबर कुछ नहीं है, और ? operator की सुविधा proper handling को छोड़ देने की संभावना बना सकती है”
    लेकिन सुविधा का मतलब errors को ignore करना कैसे हो गया, यह समझ नहीं आता
    Go के तरीके की आधी समस्या यह है कि यह result के बारे में कुछ भी enforce नहीं करता और error checking भी सिर्फ न्यूनतम स्तर पर enforce करता है
    x, err := strconv.Atoi("123"); fmt.Println("result:", x) में declared and not used: err आता है, लेकिन दूसरे conversion के बाद err check न करने पर भी y की default value 0 की वजह से यह बिना समस्या पता चले चल सकता है
    if err != nil { } जैसा खाली छोड़ने पर भी compile और run हो जाता है, और पता नहीं चलता कि कुछ गलत है
    return value को Result बना देने से यह enforce होता है कि आपको फैसला लेना ही होगा। अगर कोई ! बहुत ज्यादा इस्तेमाल करे या ? से आसानी से ऊपर propagate करते हुए error case handle न करे, तो क्या फिर panic भी ban करेंगे?

    • Go में sum types नहीं हैं, इसलिए Result हो ही नहीं सकता
      और हर type के लिए तय zero value होना चाहिए—इस अजीब obsession की वजह से sum types भी add नहीं कर पाते
    • मेरी समझ में इसका मतलब यह है कि अगर ? इस्तेमाल करना आसान हुआ तो कोई भी आगे errors को wrap नहीं करेगा
      यह logic बहुत संदिग्ध है
      शुरुआत से ही ? को error wrapping encourage करने के लिए design किया जा सकता है
    • वजह यह है कि Rust-style चीज़ को Go में डालते समय ठीक-ठीक equivalent form क्या होगा, यह साफ नहीं है
      उदाहरण के लिए Rust के From के बराबर Go में कैसा दिखना चाहिए?
    • ? की visibility कम है, और यह control flow branch को एक statement या expression के अंदर छिपा देता है
      Go ने ternary operator हटाकर हर branch अलग line में रखने वाला if statement चुना, इसकी एक वजह यह भी है
      breakpoints लगाना भी आसान नहीं होता, और यह error को enrich या handle करने के बजाय उसे जैसा है वैसा ऊपर भेजने को बढ़ावा देता है
    • मैं समझता था कि := single-statement declaration और assignment है, लेकिन example की 5वीं line में क्या err दोबारा declare होकर नया err पुराने err को shadow नहीं कर रहा?
      अगर ऐसा है, तो नया err variable use नहीं हुआ, इसलिए declared and not used: err से fail होना चाहिए लगता है
      या अगर variable पहले से मौजूद हो तो := बस normal assignment की तरह काम करता है?
  • “error में stack trace नहीं होने की बात helper function से enriched error बनाकर return कराने से solve हो सकती है” कहना reality को बहुत ज्यादा optimistic मानना है
    जिन languages में stack trace होता है, वे यह मुफ्त में देती हैं, लेकिन Go में हर बार implement करना पड़ता है
    आप खुद हमेशा details जोड़ने वाले disciplined developer हो सकते हैं, लेकिन team के सभी लोग वही discipline नहीं रखते
    stack trace की सबसे अच्छी बात यह है कि यह error तक पहुंचने वाला call path देता है
    कई जगहों से call होने वाले method में error आए, तो stack trace से तुरंत पता चल जाता है कि कौन-सा path लिया गया था
    कई सालों तक sysadmin/SRE जैसे काम करते हुए मैंने बहुत सारी समस्याएं हल की हैं, और stack trace होने पर आसान issues में कारण इतना obvious होता था कि 1–2 मिनट में काम खत्म हो जाता था
    Go में अगर किसी ने error enrich नहीं किया या वही error message reuse कर लिया, तो आसान issue भी detective work बन जाता है और ज्यादा समय लेता है