Go अभी भी अच्छा नहीं है
(blog.habets.se)- Go भाषा के कई डिज़ाइन फ़ैसले अनावश्यक थे या पहले से मौजूद अनुभवों को नज़रअंदाज़ करते हुए किए गए
- error variable की scope management की समस्या कोड की readability और bugs ढूँढना कठिन बना देती है
- nil की द्वैधता, memory usage, code portability आदि कई हिस्सों में non-intuitive और वास्तविकता से मेल न खाने वाला डिज़ाइन दिखाई देता है
- defer statement की सीमाएँ और standard library का exception handling तरीका exception safety सुनिश्चित करना कठिन बना देता है
- memory management और UTF-8 handling की कमियाँ जैसी जमा होती समस्याएँ लंबे समय में Go codebase की quality पर नकारात्मक असर डाल रही हैं
Go भाषा पर दीर्घकालिक आलोचना
- जैसा कि पिछली पोस्टों में बताया गया है(Why Go is not my favourite language, Go programs are not portable), मैं 10 साल से अधिक समय से Go भाषा की कई समस्याओं की ओर इशारा करता रहा हूँ
- खास तौर पर, पहले से ज्ञात अच्छे उदाहरणों को नज़रअंदाज़ करने वाले अनावश्यक डिज़ाइन फ़ैसले समय के साथ और अधिक खटकते हैं
error variable scope की non-intuitive प्रकृति
- Go का syntax error variable (
err) की scope को अनावश्यक रूप से बढ़ा देता है, जिससे गलती की संभावना बढ़ती है- उदाहरण कोड में
errvariable पूरे function में मौजूद रहता है और reuse होता है, जिससे code readability और maintainability घटती है - अनुभवी developers इस scope समस्या के कारण bug hunting में भ्रम और समय की बर्बादी का सामना करते हैं
- variables को उचित रूप से local scope तक सीमित करने का तरीका syntax में उपलब्ध नहीं है
- उदाहरण कोड में
nil के दो रूप
- Go में interface type और pointer type में
nilअलग-अलग तरह से behave करता है, जिससे भ्रम पैदा होता है- नीचे दिए गए उदाहरण की तरह,
s(pointer) औरi(interface) दोनों मेंnilassign होने पर भीs==iका परिणाम अलग आ सकता है, यानी असंगत व्यवहार दिखता है - यह null handling में उन समस्याओं जैसा है जिनसे आमतौर पर बचना चाहा जाता है, और यह बिना पर्याप्त डिज़ाइन-विचार के बने होने का संकेत देता है
- नीचे दिए गए उदाहरण की तरह,
कोड portability की सीमाएँ
- conditional compilation के लिए comments का उपयोग maintainability और portability के लिहाज़ से काफ़ी अप्रभावी है
- अगर आपने सच में portable software बनाया है, तो समझेंगे कि यह तरीका झंझटभरा और error-prone है
- ऐतिहासिक अनुभवों (code portability, व्यावहारिक उदाहरणों) को नज़रअंदाज़ किया गया है
- अधिक जानकारी के लिए Go programs are not portable देखें
append की ownership की अस्पष्टता
appendfunction और slice की ownership का संबंध स्पष्ट नहीं है, जिससे code behavior का अनुमान लगाना कठिन हो जाता है- उदाहरण से पता चलता है कि
foofunction में slice परappendकरने से मूल डेटा पर वास्तव में क्या असर पड़ेगा, यह पहले से जानना आसान नहीं है - भाषा में ऐसे याद रखने वाले ‘quirk’ बढ़ते जाते हैं, जो गलतियों को जन्म देते हैं
- उदाहरण से पता चलता है कि
defer statement का अपर्याप्त डिज़ाइन
- यह RAII(Resource Acquisition Is Initialization) सिद्धांत की तरह resource release को स्पष्ट रूप से support नहीं करता
- Java और Python के structured resource management syntax की तुलना में, Go में यह स्पष्ट नहीं होता कि कौन-सा resource
deferसे release होना चाहिए - उदाहरण की तरह, file operations में double-close समस्या तक को developer को ख़ुद संभालना पड़ता है, और सही release order व तरीका स्पष्ट नहीं होता
- Java और Python के structured resource management syntax की तुलना में, Go में यह स्पष्ट नहीं होता कि कौन-सा resource
standard library में exception handling
- Go explicit exception को support नहीं करता, फिर भी
panicजैसी exceptional स्थितियाँ बनी रहती हैं- कुछ स्थितियों में
panicपूरे program को पूरी तरह बंद नहीं करता और अंदर ही दबा रह जाता है - standard library (
fmt.Print, HTTP server आदि) में exceptions को ignore करने वाले patterns मौजूद हैं, इसलिए वास्तविक exception safety की गारंटी संभव नहीं - नतीजतन exception-safe code लिखना ज़रूरी है, लेकिन exceptions को सीधे इस्तेमाल नहीं किया जा सकता
- कुछ स्थितियों में
UTF-8 handling और strings
stringtype में मनचाहा binary data डालने पर भी Go बिना किसी विशेष validation के काम करता रहता है- UTF-8 encoding से पहले बने filenames जैसी चीज़ें चुपचाप छूट जाने के मामले सामने आ सकते हैं
- backup जैसे कामों में महत्वपूर्ण data खो सकता है, और यह वास्तविक कामकाजी स्थितियों को न दर्शाने वाला अत्यधिक सरल तरीका है
memory management की सीमाएँ
- RAM usage पर सीधा नियंत्रण कठिन है, और GC(garbage collection) की विश्वसनीयता की भी सीमाएँ हैं
- Go की memory usage बढ़ती जाती है, जो लंबे समय में cost और performance issues से जुड़ती है
- कई instances और container environments में cost और scalability की समस्याएँ वास्तव में सामने आती हैं
निष्कर्ष: बेहतर रास्ता मौजूद था
- पहले से प्रभावी रूप से सिद्ध language designs मौजूद होने के बावजूद, Go ने कई मामलों में उन्हें नज़रअंदाज़ किया
- Java के शुरुआती संस्करणों की समस्याओं से अलग, Go के रिलीज़ होने तक बेहतर approaches पहले से उपलब्ध थे
संदर्भ सामग्री
- Uber: Data race patterns in Go
- FasterThanLime: Lies we tell ourselves to keep using Golang
- FasterThanLime: I want off Mr Golang’s wild ride
1 टिप्पणियां
Hacker News राय
मैं pre-1.0 दौर से ही लगभग हर full-time नौकरी में Go इस्तेमाल करता आया हूँ। टीम के लोगों के लिए basics सीखना आसान है, और यह ज़्यादातर स्थिर रूप से काम करता है। Go के नए version पर update करते समय लगभग कभी चिंता नहीं होती, और ज़्यादातर उपयोगी features default रूप से शामिल रहते हैं। इसका fast compile speed आकर्षक है। concurrency थोड़ा पेचीदा हो सकता है, लेकिन समय लगाने पर data flow को व्यक्त करने के लिए अच्छा लगने लगता है। type system ज़्यादातर सुविधाजनक है, हालांकि कभी-कभी थोड़ा verbose लगता है। कुल मिलाकर यह भरोसेमंद tool है। लेकिन लेख में बताए गए कई points से मैं सहमत हूँ। Go में साफ़ दिखता है कि पुरानी पीढ़ी के developers ने principles पर ज़रूरत से ज़्यादा ज़ोर दिया और practical convenience को कुछ हद तक छोड़ा। बेशक यह मेरी भावना है, और अगर इसकी सारी कमियाँ दूर कर दी जातीं तो शायद यह आज से भी बदतर होता। यह भी कहना चाहूँगा कि पिछले कुछ वर्षों में quirks को ठीक करने के लिए माहौल ज़्यादा खुला लगा है। एक समय था जब मैं कल्पना भी नहीं कर सकता था कि generics या custom iterators जोड़े जाएँगे। RAM और portability को लेकर की गई आलोचना मुझे कुछ हद तक निजी शिकायत जैसी लगती है। सुधार हो तो अच्छा है, लेकिन GC ज़्यादातर programs में गंभीर समस्या पैदा करे ऐसा बहुत कम होता है, और debugging भी बहुत मुश्किल नहीं है। और Go लगभग सभी महत्वपूर्ण platforms को support करता है। फिर भी error और nil को handle करने का तरीका मुझे लगातार असुविधाजनक लगता है।
Result[Ok, Err],Optional[T]जैसे syntax की अक्सर कमी महसूस होती हैमुझे तो उल्टा लगता है कि Go ने principles पर ज़िद नहीं की, बल्कि सामने दिख रही समस्या को जल्दी निपटाने वाली convenience पर ज़रूरत से ज़्यादा ज़ोर दिया। समस्या का मूलभूत विश्लेषण करके सही समाधान निकालने के बजाय, ऐसा लगा जैसे ‘Not Invented Here’ मानसिकता छोड़कर मौके पर जो बन पड़ा वही जोड़ दिया गया। Go का filesystem API इसका प्रतिनिधि उदाहरण है। अगर file खोलने का function चाहिए, तो बस
func Open(name string) (*File, error)जैसा कुछ बना दिया और बात खत्म। लेकिन अगर file name UTF-8 न हो तो? 5 साल तक वह समस्या सामने नहीं आई, तो किसी ने ध्यान ही नहीं दियामुझे अक्सर लगता है कि Go के design principles का झुकाव “compiler को आसान बनाओ और compilation तेज़ करो” इस लक्ष्य की ओर बहुत ज़्यादा है। developer convenience की तुलना में compiler/compilation पर ही इसका ज़ोर अधिक दिखता है
20 साल बाद किसी compiled language के साथ नई नौकरी में मैंने पहली बार Go को ठीक से इस्तेमाल किया। यह शायद व्यक्तिगत पसंद की बात हो, लेकिन सच कहूँ तो इसे इस्तेमाल करते समय झुंझलाहट भी हुई। default argument values नहीं हैं, error handling का तरीका पसंद नहीं आया, production में ठीक-ठाक stack trace नहीं मिलता। object-oriented syntax में हर function पर अजीब-सा receiver लगाना पड़ता है, जिससे पढ़ना अच्छा नहीं लगता। pointers भी बोझ जैसे लगते हैं। अंततः ऐसा महसूस हुआ जैसे C/C++ के पुराने ज़माने में लौट आया हूँ। कॉलेज के दिनों, लगभग 1999 के आसपास की programming वाली भावना ही लौट आई
concurrency के मामले में, मेरे अनुभव में Go ही एकमात्र ऐसी system language है जो multi-core CPU environment में parallelism को language स्तर पर स्वाभाविक ढंग से संभालती है। CSP शैली के goroutine/channel मॉडल की वजह से parallel processing logic सहज रूप से व्यक्त होता है। Python में GIL और उलझे हुए async libraries सिरदर्द हैं। C, C++, Java जैसी भाषाओं में language के बाहर अतिरिक्त libraries चाहिए, इसलिए language स्तर पर concurrency के बारे में तर्क करना आसान नहीं होता। इसलिए HTTP server या services के लिए go मुझे बिल्कुल उपयुक्त लगता है। मेरे अनुभव में इसका कोई अच्छा विकल्प नहीं है
developer perspective से ergonomics, यानी standardization और consistency के मामले में यह लगभग परफ़ेक्ट लगा। कई microservices codebases में भी style अलग-अलग होने की चिंता नहीं रहती, और formatting पर बहस की ज़रूरत नहीं पड़ती। लेकिन Go ने अपनी standard शैली चुनते समय कुछ पुराना अंदाज़ शायद ज़रूरत से ज़्यादा पकड़े रखा। आज के developers
map/filterजैसे functional methods की अपेक्षा करते हैं, जबकि Go सिर्फ loops देता है जिनमें index mistakes का जोखिम रहता है। इसका type system भी TypeScript जितना smart नहीं है। error handling असुविधाजनक है। मैं समझता हूँ कि ऐसे features जोड़ने से “creative लेकिन बुरी usage” बढ़ सकती है, लेकिन JS पीढ़ी के लोगों को go के लिए राज़ी करना मुश्किल है, यह भी सच हैमैं 5 साल से ज़्यादा समय से एक बड़े Golang project पर केंद्रित हूँ, और जब memory usage को न्यूनतम रखना पड़ने वाले components बनाता हूँ तो Go की ढीली जगहों से बार-बार सामना होता है। GC जल्दी साफ़ नहीं करता या heap fragmentation बहुत गंभीर हो जाती है (क्योंकि Go compacting garbage collector नहीं है)। इस वजह से allocations से पूरी तरह बचने की कोशिश करनी पड़ती है, लेकिन इससे bugs आने की संभावना बढ़ जाती है। debugging भी बेहद कठिन है। heap profile लेने पर सिर्फ़ surviving objects की जानकारी मिलती है; असल जमा हुआ garbage या fragmentation दिखाई नहीं देता, इसलिए अनुमान लगाना पड़ता है। उदाहरण के लिए, कोई function X heap पर सिर्फ़ 1KB allocate करता दिखता है, लेकिन अगर वह loop में बार-बार call हो तो दर्जनों MB garbage बन सकता है। इसलिए हम static buffers पहले से allocate करके reuse करते हैं, लेकिन ownership के सवाल जटिल हो जाते हैं और
appendजैसी कमजोरियाँ सामने आती हैं। कभी-कभी standard library को भी खुद फिर से implement करना पड़ता है। मुझे पता है कि हमारा मामला सामान्य नहीं है, लेकिन सच में ऐसा लगता है जैसे भाषा से लड़ना पड़ रहा होऐसे मामलों में memory को heap के बाहर ले जाना शायद कम तकलीफ़देह हो सकता है। बेशक GC language होने की वजह से यह आसान नहीं है, लेकिन Go में ज़बरदस्ती C++/Rust-स्टाइल code लिखने से बेहतर है कि उस हिस्से को सीधे उसी language में कर दिया जाए
मुझे लगता है कि ऐसी स्थिति में go चुनना ही मूल समस्या थी। C/C++/Rust/Zig अधिक उपयुक्त होते
खबर है कि नया "Green Tea" garbage collector मददगार हो सकता है। यह memory-केंद्रित न होते हुए भी memory-adjacent objects को बेहतर संभालने वाला parallel mark algorithm है। संबंधित जानकारी यहाँ देखी जा सकती है
arenaexperiment चल रहा था, लेकिन अभी रुका हुआ है। फिर भी ध्यान देने लायक हैयह शायद मददगार बात नहीं है, माफ़ कीजिए, लेकिन आपकी मौजूदा स्थिति देखकर मुझे लगता है कि language choice पूरी तरह ग़लत थी। शायद कंपनी की internal language policy की वजह से आप go का इस्तेमाल करने को मजबूर हैं। बड़े enterprises में अक्सर सिर्फ़ व्यापक रूप से इस्तेमाल होने वाली languages को ही production के लिए मंज़ूरी मिलती है
मैं अब तक नहीं समझ पाया कि Go में
deferसिर्फ़ function scope पर ही क्यों काम करता है, lexical scope पर क्यों नहीं। मुझे यह बात तब समझ आई जब loop के अंदर files process करते हुए file list बड़ी हो गई औरdeferfunction खत्म होने तक handles बंद नहीं कर रहा था, जिससे crash हो गया। आसपास के Go developers ने कहा कि loop body को anonymous function में wrap करके लिखो। इसके अलावा कुछ छोटी-मोटी बातों को छोड़ दें तो Go काफ़ी सुखद लगता है, इसकी efficient syntax है, और यह बेकार की ‘show-off’ संस्कृति को भी रोकता है। मैंने एक बड़े C# project को Go में rewrite किया था; features एक-दसवें थे, फिर भी code कम था। यह GC allocations को मजबूर करने के बजाय performance-friendly defaults की ओर प्रेरित करता है, और serialization जैसे कामों के लिए built-in code generation सुविधाजनक है। C# syntax की तरह सब कुछ भाषा के भीतर समेटने की कोशिश नहीं होती; Go में SQL को बस SQL की तरह लिखते हैं, और gRPC को protobuf spec से handle करते हैंकभी lexical scope वाला
deferचाहिए होता है, और कभी function scope वाला। उदाहरण के लिए, अगर loop में कई files खोलकर function खत्म होने तक सबको खुला रखना हो, तो function scope ज़रूरी है। अभी function scope मौजूद है, और lexical scope चाहिए तोfuncमें wrap कर सकते हैं। अगर सिर्फ़ lexical scope होता और function scope चाहिए होता, तो क्या करते, यह उतना स्पष्ट नहीं हैwrapping function के बिना एक स्तर की indentation कम हो जाती है, इसका behavior call stack या stack unwinding से जुड़ा है, और C के ‘goto fail’ style से देखें तो यह स्वाभाविक लगता है। बेशक, loop में
deferइस्तेमाल करते समय अलग से function में wrap करना थोड़ा असुविधाजनक हैमैंने block-level और function-level दोनों तरह के
deferइस्तेमाल किए हैं, और कभी-कभी लगता है कि conditionals के अंदर भी function-leveldeferइस्तेमाल कर पाता तो अच्छा होतामुझे नहीं लगता कि इसके पीछे कोई बहुत गहरा कारण है; सवाल यह है कि क्या यह सच में इतना महत्वपूर्ण है
C# में भी SQL या protobuf spec के साथ काम किया जा सकता है। बस वहाँ दूसरे विकल्प भी मौजूद हैं
Go में कमियाँ बहुत हैं, लेकिन server-side languages की श्रेणी में मुझे इससे ज़्यादा balanced language नहीं दिखती। यह Node या Python से तेज़ है, और मेरा मानना है कि इसका type system भी बेहतर है। Rust की तुलना में इसकी entry barrier कम है, और standard library व tooling भी शानदार हैं। इसकी simple syntax और “एक ही तरीका” लागू करने वाली सोच भी मुझे पसंद है। error handling में समस्या है, लेकिन Node की तरह
catchमें कोई भी error आ जाने से तो बेहतर है। सोचता हूँ, क्या कोई और language है जो ये सारे मानदंड पूरा करती हो? मैं खुद Go का अंधभक्त नहीं हूँ; अपने करियर में backend ज़्यादातर Node पर किया है, लेकिन हाल में Go को प्रयोग के तौर पर इस्तेमाल कर रहा हूँसच कहें तो यही सारी खूबियाँ Java या C# पर भी लागू हो सकती हैं
‘Node’ को programming language कहना थोड़ा खटकता है। Node एक JavaScript runtime है, और आजकल Node पर चलने वाले बहुत-से projects वास्तव में TypeScript में लिखे होते हैं। यानी Node कहने से इस्तेमाल की जा रही language स्पष्ट नहीं होती। अगर TypeScript को आधार मानें, तो मुझे इसका type system Go से ज़्यादा productive लगता है। Rust के साथ तुलना में भी यही बात कही जा सकती है
ज़्यादातर भाषाओं में अपनी-अपनी असुविधाएँ होती हैं। Go की performance, portability, runtime और ecosystem अच्छे हैं। दूसरी ओर nil pointers, zero value, destructor का अभाव, macros का अभाव जैसी कमियाँ भी हैं (Go में macros नहीं होने की भरपाई के लिए code generation का दुरुपयोग होता है)। इससे बेहतर languages भी हैं (जैसे Rust), लेकिन वे Go से काफ़ी ज़्यादा जटिल भी हो जाती हैं। इसकी वजह यह है कि Go के creators ने simplicity को सर्वोच्च प्राथमिकता दी
Python के type system में हाल के वर्षों में हुए विकास को देखें तो वह Go से काफ़ी आगे लगता है। सिर्फ़ structural typing की बात करें तो Python ज़्यादा प्रभावशाली है
मुझे लगता है कि Go का type system काफ़ी कमज़ोर है
मैंने Go में बने एक static site generator को extend किया था। code बहुत स्पष्ट और पढ़ने में आसान था, लेकिन language की सीमाओं के कारण extensibility कम थी। छोटे बदलाव के लिए भी code के कई हिस्सों में मुश्किल से बदलाव करना पड़ता था। अलग-अलग स्तर की encapsulation और abstraction बनाना कठिन है, और ‘simplicity’ के लिए abstraction की बलि दे दी गई है। abstraction ही extensible code बनाने का सबसे महत्वपूर्ण तरीका है, लेकिन Go ने extensibility की बजाय simplicity चुनी। ज़्यादातर Go programs मुझे “extensibility रहित simplicity” तक सीमित लगते हैं। लोग कहते हैं कि Go ऐसी ही language है, लेकिन मेरे अनुभव में यह बात आसानी से स्वीकार नहीं होती। हाँ, ‘developer experience’ कम से कम बहुत खराब नहीं है
Go के बारे में बातचीत हमेशा थोड़ी अजीब लगती है। जैसे ही आप आलोचना करें, ज़्यादातर जवाब होता है “यह भाषा ऐसी ही है”, मानो बस उसे स्वीकार कर लो। simplicity को इसकी ताकत बताया जाता है, लेकिन अगर
mapकी keys की list निकालने के लिए भी loop खुद लिखना पड़े, तो क्या वह सच में ज़्यादा simple है?मैं पूछना चाहूँगा कि क्या थोड़ी-सी Go इस्तेमाल करके इस तरह की आलोचना करना ठीक है। मैंने 2015 से countless बड़े Go codebases (लाखों lines) देखे हैं और कई teams में काम किया है। C, C#, Java की तुलना में Go की extensibility कोई विशेष रूप से कम नहीं है। Go expressiveness की जगह clarity चुनता है। इसलिए abstraction layers कम होते हैं और code ज़्यादा concrete व explicit लिखा जाता है। लेकिन इससे यह नहीं निकलता कि विस्तार संभव नहीं है। modular और extensible design कोई language अपने-आप नहीं देती; यह developers सीखते हैं। संभव है कि जिस code पर आपने काम किया वह खराब design किया गया था; यह Go language की सीमा नहीं है
मैंने Go को कई साल इस्तेमाल किया है। छोटी चीज़ें जल्दी बन जाती हैं, लेकिन scale बढ़ने पर असंख्य छोटी असुविधाएँ परेशान करती हैं। debugging ख़ास तौर पर दुःस्वप्न जैसी है, क्योंकि अगर कोई unused X बच जाए (जो debugging के दौरान किसी हिस्से को comment out करते समय हमेशा हो जाता है), तो compilation ही नहीं होता। अनावश्यक औपचारिकता, खास file names, और reserved field names भी झंझट बढ़ाते हैं। standard library में छिपे
panic, और अप्रत्याशित heap copies भी धीमे और परेशान करने वाले हैं। Go के ‘magical’ हिस्से ज़्यादातर पहले से मौजूद features (special file names, capitalization वगैरह) को ज़बरदस्ती मोड़कर इस्तेमाल करने के side effects हैं। सच में अगर “public” जैसा कुछ चाहिए था, तोpubलिखने देते; यह अजीब ज़िद जैसी लगती है। आजकल AI इतना अच्छा हो गया है कि Rust में type problems या borrow checker issues आते ही मैं AI से पूछकर जल्दी समाधान निकाल लेता हूँ, इसलिए वह कहीं ज़्यादा सुखद लगता है। पहले की तरह docs या SO खंगालने में समय बर्बाद नहीं करना पड़तामैंने हाल में Rust को गंभीरता से नहीं अपनाया, लेकिन पिछले दिसंबर में थोड़ा इस्तेमाल किया तो हैरानी हुई कि AI Rust के साथ कितना अच्छा काम करता है। उसमें विस्तृत syntax और explicit type information अधिक होने की वजह से कभी-कभी AI इंसानों से भी बेहतर हल निकाल देता है
जब आप Go में debugging के दौरान compilation errors की शिकायत करते हैं, तो Go समुदाय की ओर से जवाब मिलता है कि “tools सही से इस्तेमाल करो।” principles को बहुत चरम पर ले जाने की वजह से असुविधा पैदा होती है
मैंने debugging से जुड़ी इस असुविधा के बारे में Go के एक creator से बात की थी, लेकिन वह भी समस्या समझ नहीं पाया। यह मुझे बहुत amateurish लगा और निराशा हुई। और वैसे, AI Go के साथ उतना अच्छा नहीं है। भाषा अपेक्षाकृत simple है, फिर भी ChatGPT Java, C#, Python को ज़्यादा बेहतर support करता है
व्यक्तिगत रूप से मुझे Go पसंद नहीं है और इसकी कई निर्णायक कमियाँ दिखती हैं, लेकिन इसके लगातार लोकप्रिय बने रहने के कारण भी स्पष्ट हैं। Go तुलनात्मक रूप से तेज़ है, और goroutine-आधारित मॉडल की वजह से multi-threading को सीधे संभाले बिना भी stable और reliable high-concurrency services लिखना आसान हो जाता है। जब Google ने Go जारी किया था, तब इसी तरह की लोकप्रिय, static, compiled language लगभग नहीं थी। आज भी इसी स्थान पर वास्तविक प्रतिद्वंद्वी सिर्फ़ Java है (अब virtual threads के साथ)। async/await वाली भाषाएँ भी ऐसे ही वादे करती हैं, लेकिन व्यवहार में उनमें काफी जटिलता होती है (async tasks में blocking से बचना, function coloring आदि)। Erlang एक अलग श्रेणी है। इसलिए, कमियों के बावजूद goroutines और Google project होने की brand value की वजह से इसकी लोकप्रियता ऊँची बनी हुई है
धीरे-धीरे JVM Go के साथ अंतर कम कर रहा है। virtual threads, zgc, lilliput, Leyden, Valhalla जैसे projects के ज़रिए चीज़ें लगातार बेहतर हो रही हैं। Java 8 से 25 तक के बदलाव बहुत बड़े हैं। आगे यह और सुविधाजनक होता दिख रहा है
Go की explicitness और simplicity LLM-assisted programming के लिए बहुत उपयुक्त है। पुराना Go 1.x code भी आज के latest versions में ठीक से चलता है
वास्तव में Google के अंदर virtual threads वाली Java का उपयोग Go से कहीं ज़्यादा होता है
मुझे जिज्ञासा है कि नए projects के लिए सबसे उपयुक्त “modern language” आप किसे मानते हैं
मैं 1.0 release से पहले से Go को पसंद करता रहा हूँ, लेकिन “अब तक इसे बना नहीं पाए” जैसी राय से मैं सहमत नहीं हूँ। कमियाँ और शिकायतें ज़रूर हैं, लेकिन मेरा मानना है कि अगर creators project छोड़ दें तो central vision को बनाए रखना कठिन हो जाता है और भाषा बिगड़ने का जोखिम बढ़ जाता है। इसे सिर्फ़ “server language” के रूप में position करना भी अंततः लोगों को Rust या Python जैसी दूसरी भाषाओं की ओर धकेल सकता है। एक समय Visual Basic का भी मज़ाक उड़ाया जाता था, लेकिन जिसे ज़रूरत थी वह उसे अच्छे से इस्तेमाल करता था
Go की कमियों पर लिखी आलोचनात्मक पोस्टों को ध्यान से देखें तो वे अक्सर इतने बड़े मुद्दे नहीं होते। ज़्यादातर बातें तकनीकी रूप से सही हैं, पर अपेक्षाकृत मामूली हैं। उल्टा, सच में गंभीर language design समस्याएँ हैं:
zero value, constructor support का अभाव, null handling की कमजोरी, default mutability, generics को ध्यान में रखकर न बनाया गया type system, arbitrary precision को support न करने वालाint, और अस्पष्ट ownership वालाslice(संबंधित issue 1, संबंधित issue 2)।sum typeका अभाव, string interpolation का न होना जैसी बातें भी कमियाँ हैंमैं शायद पक्षपाती हूँ क्योंकि Go पर किताब तक लिखी है, लेकिन 10 साल से अधिक समय तक Go इस्तेमाल करने वाले व्यक्ति के रूप में कहूँ तो शुरुआत में यह सचमुच ताज़गीभरा लगा था। Java की तुलना में boilerplate कम है, सीखना आसान है, और performance भी ठीक-ठाक है। कोई एक सर्वश्रेष्ठ language नहीं होती; हर उपयोग के लिए अलग सर्वोत्तम विकल्प हो सकता है, लेकिन typical backend कामों के लिए यह ऐसा चुनाव है जिस पर पछतावा नहीं होता