1 पॉइंट द्वारा GN⁺ 2024-02-08 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • for लूप वेरिएबल अब हर iteration में नया बनाया जाता है, जिससे अनजाने shared bugs से बचा जा सके; integers पर range भी अब संभव है
  • Compatibility Go 1 compatibility promise को बनाए रखती है, और उम्मीद है कि लगभग सभी Go programs पहले की तरह compile और run होंगे
  • Workspace में go work vendor से बनाई गई vendor directory का उपयोग किया जा सकता है, और यदि workspace vendor मौजूद है तो -mod=vendor default बन जाता है
  • GO111MODULE=off वाले legacy GOPATH mode में module के बाहर go get support हटा दिया गया है, लेकिन go build और go test जैसे दूसरे build commands legacy GOPATH programs में काम करते रहेंगे
  • Runtime अब heap objects के पास type-based GC metadata रखता है, जिससे Go programs की CPU performance में 1–3% सुधार होता है और कई programs का memory overhead लगभग 1% कम होता है
  • कुछ object address alignment पहले के 16-byte या उससे अधिक की जगह 8-byte alignment में बदल सकते हैं; अधिक alignment मानकर लिखे गए assembly code को संशोधित करना होगा, और अस्थायी workaround GOEXPERIMENT=noallocheaders उपलब्ध है
  • PGO builds अब अधिक calls को devirtualize कर सकते हैं, और representative Go programs के set में PGO enabled होने पर runtime performance 2–14% बेहतर होती है
  • Standard library में पहला v2 package math/rand/v2 जोड़ा गया है; इसमें Read inherited नहीं है, globally shared generator हमेशा random seed लेता है, ChaCha8 और PCG sources हैं, और generic function N दी गई है
  • net/http.ServeMux routing patterns अब methods और wildcards को support करते हैं; {} वाले patterns और escaped paths के handling में छोटे backward-compatibility breaks हैं, और GODEBUG=httpmuxgo121=1 से पुराना behavior वापस लाया जा सकता है
  • crypto/tls server का default minimum version अब, अगर explicitly set न हो, TLS 1.2 है; और pre-TLS 1.3 handshakes में ECDHE के बिना cipher suites अब default में उपलब्ध नहीं हैं
  • Execution tracer को पूरी तरह पुनर्निर्मित किया गया है: यह अधिकांश platforms पर OS clock का उपयोग करता है, streaming processing वाले split traces support करता है, full syscall duration दिखाता है, और यह भी बताता है कि goroutine किस OS thread पर चली
  • trace tool का web UI नए tracer support कार्य के हिस्से के रूप में अपडेट किया गया है, और Go 1.22 या बाद के version से बने programs के traces में thread-oriented view तथा full syscall duration display support जोड़ा गया है
  • vet ने Go 1.22 loop variable semantics के अनुसार loop closure warnings को समायोजित किया है, और valueless append, defer के भीतर non-deferred time.Since, तथा log/slog key/value mismatch के लिए नई warnings जोड़ी हैं
  • Bootstrap के लिए Go 1.20 का अंतिम point release या उससे नया version चाहिए; और उम्मीद है कि Go 1.24 को Go 1.22 के अंतिम point release या उससे नया version चाहिए होगा
  • darwin/amd64 पर Go toolchain अब default रूप से PIE बनाता है; Go 1.22 macOS 10.15 Catalina पर चलने वाली आखिरी release है, और Go 1.23 के लिए macOS 11 Big Sur या नया version चाहिए होगा
  • go/types में Alias type और Unalias function जोड़े गए हैं; gotypesalias=1 में clients को Alias type संभालना होगा
  • slices.Delete, DeleteFunc, Compact, CompactFunc, Replace अब shrunk segment के elements को zero करते हैं, और Insert में यदि i range से बाहर हो तो हमेशा panic होगा
  • Windows directory reading functions अब entries को batch में पढ़ते हैं, जिससे system calls कम होते हैं और performance अधिकतम 30% तक बेहतर होती है

1 टिप्पणियां

 
GN⁺ 2024-02-08
Hacker News की राय
  • पिछले 3 सालों में मैं मुख्यतः TypeScript इस्तेमाल कर रहा था, लेकिन हाल ही में Go इस्तेमाल करना शुरू किया। शुरुआत में arrays के लिए functions की कमी और कम flexible type system की वजह से थोड़ी चिंता थी
    लेकिन जब मैंने 4~5 लोगों की टीम के लिए TypeScript project फिर से सेटअप किया, तो linting, server routing library चुनना, server चुनना, coding standards, basic error handling, nested try/catch की नरक जैसी स्थिति से बचने के लिए custom errors या Result type लागू करना, testing और mocking, Prisma setup वगैरह में बहुत ज़्यादा समय लग गया
    मुझे TypeScript पसंद है, लेकिन बेहतरीन standard library, सही type safety, और built-in coding standards वाली भाषा इस्तेमाल करना सच में बहुत सुविधाजनक है। Go में भी कुछ quirks हैं, लेकिन वह काफ़ी अच्छा है, और routing का standard library में आ जाना भी अच्छा है क्योंकि अब एक चीज़ कम सोचनी पड़ती है। अब बस slices के लिए map/filter/find functions का इंतज़ार है

    • एक CTO newsletter में हाल ही में TypeScript और Go releases की तुलना की गई थी, और उदाहरण के तौर पर Go 1.22 लिया गया था
      TypeScript हर release के साथ power users के लिए और जटिल होता जा रहा है, जबकि Go range over integers जैसी छूटी हुई चीज़ें जोड़कर इस्तेमाल को और सरल बनाता है
      यह कुछ वैसा है जैसे game sequels settings और mechanics बढ़ाते-बढ़ाते नए users के लिए reset की ज़रूरत वाली स्थिति में पहुँच जाते हैं; programming languages में ऐसा करना कठिन होता है, इसलिए अच्छा है कि Go इस बात को ध्यान में रखता है
    • मुझे भी कुछ ऐसा ही लगा। जिस चीज़ ने मुझे Go पर टिकाए रखा, वह था हैरान करने वाला एकरूप build toolchain, और go:embedgo:generate से जो कुछ किया जा सकता है, वह दूसरे projects में देखते समय हर बार प्रभावित करता है
      golang.org/x packages भी बहुत अच्छे हैं क्योंकि लगभग सभी internet RFC implementations तुरंत इस्तेमाल के लिए तैयार मिल जाते हैं
    • slices के लिए map/filter/find आने तक, lodash से प्रेरित lo library इस्तेमाल की जा सकती है
      यह Go projects में मेरी पसंदीदा all-purpose utility है: https://github.com/samber/lo
    • इसमें बहुत ज़्यादा features नहीं हैं, इसलिए उल्टा छोटे-छोटे फैसले कम हो जाते हैं, और intuition के विपरीत यह काफ़ी productive है
    • मैं कुछ समय एक ऐसे client के लिए काम कर रहा था जो TypeScript इस्तेमाल करता था, और बाद में मैंने इसे “Tricks Driven Development” कहना शुरू कर दिया
      आप कुछ करने के लिए documentation पढ़ते, और थोड़ी देर बाद कोई आपको documentation में न लिखा हुआ कोई काम का trick बता देता—ऐसा बार-बार हुआ
  • अगर official release notes थोड़े सूखे लगते हों, तो किसी ने उनका interactive version बनाया है: https://antonz.org/go-1-22

    • for loop variable sharing की समस्या पहले मुझे तुरंत समझ नहीं आई, लेकिन उसे खुद चलाकर अनपेक्षित परिणाम देखना मददगार रहा
    • Compact और Replace के examples भ्रमित करते हैं; पता नहीं यह सही है या नहीं
  • मैंने Go को 9 साल से अधिक इस्तेमाल किया है, और पिछले 4 सालों में Flutter की वजह से Dart भी बहुत इस्तेमाल किया है। मेरे हिसाब से दोनों भाषाओं का complexity के प्रति रवैया बिल्कुल उल्टा है। Dart हर संभव feature जोड़ना चाहती है, जबकि Go इसका उल्टा करती है
    पहली बात, Dart में class के अंदर values initialize करने के बहुत ज़्यादा तरीके हैं, और इसी में बहुत समय चला जाता है। final/const/static/late prefixes के अनुसार constructor, factory, Flutter StatefulWidget का initState() आदि में initialization की जगह बदलती रहती है, और refactoring करने पर initialization को बड़े पैमाने पर बदलना पड़ता है। variables जैसे दिखने वाले getter भी नए codebase में और भ्रम पैदा करते हैं
    दूसरी बात, Dart में maps, streams जैसी कई सुविधाएँ हैं जिन्हें एक ही line में ठूँसना आसान है, इसलिए समझने में मुश्किल one-liner code जल्दी बन जाता है। लेकिन debugging करते समय या जब junior developer firstWhereOrNull जैसे hacks और orElse: () => null जैसे optional parameters से टकराते हैं, तो वे बहुत भ्रमित हो जाते हैं। कई बार उलझी हुई null safety या type errors काम रोक देते हैं, और जब इसे साधारण Go-style for loop में बदल देते हैं, तो सच में राहत मिलती है

    • Dart tip के तौर पर, जो चीज़ें सीधे UI से संबंधित नहीं हैं, उनके लिए initState इस्तेमाल न करना बेहतर है। उदाहरण के लिए text field hint सेट करने जैसी मामूली चीज़ न हो तो इससे बचना चाहिए
      ज़्यादातर Flutter pages या तो बहुत कम काम करते हैं, या parent MyPageController object बनाकर अपनी पसंद के अनुसार initialize करता है और child page उस controller के हिसाब से काम करता है। उदाहरण के लिए, list page में जब user किसी item को edit करना चाहता है, तो controller बनाकर item उसमें डालकर child page को भेज दिया जाता है; वापस आने के बाद parent controller के item, variables या callbacks देखकर तय कर सकता है कि UI में क्या बदलना है
      इससे InheritedWidget जैसी चीज़ों को छुए बिना widgets के बीच interaction को बारीकी से नियंत्रित किया जा सकता है। बेशक इसे state management library के साथ इस्तेमाल करना अच्छा है, लेकिन व्यवहार में अक्सर लोग ऐसा नहीं भी करते
    • मैं भी मानता हूँ कि Go की सबसे बड़ी ताकत इसकी सरलता है। range भी ऐसा ही है—आख़िरकार टाइप किए जाने वाले characters की संख्या forEach(f) जैसी comprehension के बराबर ही होती है, बस वह तीन lines में फैला होने की वजह से लंबा दिखता है; खुद खोलकर लिखो तो कोई बड़ी बात नहीं
      हालाँकि initialization के मामले में, काश Go में struct fields को किसी खास value से initialize करने का कोई idiomatic तरीका होता। constructor न होना ठीक है, लेकिन कभी-कभी मन करता है कि bool default रूप से true initialize हो
    • initState StatefulWidget का override है और दूसरे frameworks के lifecycle events से अलग नहीं है; यह Flutter की अवधारणा है, इसलिए इसे constructor के साथ भ्रमित नहीं करना चाहिए
      सामान्य constructor और factory में क्या इस्तेमाल करना है, इसमें भ्रम हो सकता है, लेकिन सिर्फ initState की वजह से Go को श्रेष्ठ कहना मुश्किल है
    • महंगे experts को आपस में संक्षेप में संवाद कर पाने की क्षमता को optimize करना चाहिए। beginners के हाथ से शक्तिशाली syntax tools छीन लेना सिर्फ उनकी expertise बढ़ाने में बाधा डालेगा
  • io.Copy, TCPConn से UnixConn में copy करते समय जहाँ संभव हो Linux का splice(2) system call इस्तेमाल करेगा, और नया method TCPConn.WriteTo उपयोग में लाएगा
    interface upgrade के ज़रिए एक बार फिर zero-copy I/O पारदर्शी रूप से बढ़ गया है। io package में इस pattern से मिलने वाला फायदा सच में बड़ा है

    • Go standard library में इस तरह की tuning बहुत अधिक है। यह ज़रूरी नहीं कि बुरी बात हो, लेकिन ऐसे special cases extensible नहीं होते, इसलिए non-standard libraries के साथ integration कम संतोषजनक हो जाता है
      फिर भी, यह अपेक्षित दायरे के भीतर ही है
  • बेहतर routing patterns इस समय एक अच्छा सुधार हैं, खासकर जब Gorilla Mux का भविष्य अनिश्चित दिख रहा है
    हालांकि यह बदलाव छोटे स्तर पर backward compatibility तोड़ता है; कुछ हिस्से स्पष्ट हैं, जैसे { और } वाले patterns का बदला हुआ व्यवहार, और कुछ कम स्पष्ट हैं, जैसे escaped paths की handling. इसे GODEBUG के httpmuxgo121 फ़ील्ड से नियंत्रित किया जाता है, और httpmuxgo121=1 सेट करने पर पुराना व्यवहार वापस पाया जा सकता है
    लेकिन तब यह सवाल उठता है कि यह Go 1 compatibility promise से क्यों नहीं टकराता, जिसमें कहा गया है कि “Go 1 spec के अनुसार लिखा गया प्रोग्राम उस spec की पूरी उम्र तक बिना बदलाव compile होता रहेगा और सही चलेगा”

    • Backward-incompatible बदलावों को Go 1 compatibility promise से बचाकर लाने का तरीका यह है कि उन्हें go.mod के go directive के मान से बाँध दिया जाए
      1.22 या उससे ऊपर पर नया library behavior मिलता है, नहीं तो पुराना behavior. यह व्यवहार में कितना अच्छा काम करेगा, यह देखना होगा
    • आम तौर पर Go टीम कुछ तोड़ने से पहले GitHub और open source programs को scrape करके देखती है कि लोग चीज़ों का इस्तेमाल कैसे करते हैं. शायद उन्होंने देखा होगा कि HTTP handler paths में { और } का उपयोग लगभग नहीं होता
      वे नए behavior को बंद करने का तरीका भी देते हैं, इसलिए code changes मजबूरन नहीं करने पड़ते, हालांकि नया environment variable सेट करना पड़ता है
      इस रिलीज़ में for loop semantics का बदलाव भी ऐसा ही उदाहरण है; यह भी व्यवहारिक रूप से breaking change है. फिर भी सभी Go programs compile और run होते रहते हैं, बस कुछ behavior थोड़ा बदल सकता है. Go ने एक practical approach चुना है, और शायद वही उसकी सफलता के कारणों में से एक है
    • मुझे यह Go में एक दुर्लभ गलती लगती है. अगर go.mod के जरिए version के हिसाब से breaking changes करने ही हैं, तो कम से कम उन्हें बेहतर तरीके से break करना चाहिए
      जब go.mod को 1.22 पर बदलें, तब subtle runtime issues खोजने से कहीं बेहतर होगा कि code compile fail हो जाए
    • नहीं तो वह छोटा और ताकतवर marketing line खो जाती है. यह incompatible change है, चाहे छोटा हो या बड़ा
  • Go 1.22 में loop की हर iteration अब एक नया variable बनाती है
    इस पर पहले भी यहाँ चर्चा हुई थी: https://news.ycombinator.com/item?id=33160236 - Go: Redefining For Loop Variable Semantics (2022)

  • शायद मैं old-school हूँ, लेकिन functions पर range जोड़ना मुझे पसंद नहीं है. इससे जितनी complexity language में जुड़ती है, उतनी सुविधा मुझे नहीं दिखती, और functional style, Go की explicit, imperative, और verbose लेकिन कम-featured style से मेल नहीं खाती. मुझे लगता है कि यही Go की बड़ी ताकतों में से एक थी
    इसी वजह से integers पर range भी मुझे गलत दिशा लगती है. Go का lean feature set और कम cognitive load हमेशा उसकी बड़ी strengths और differentiators रहे हैं

    • अभी यह feature optional और experimental है, और इसे explicitly enable करना पड़ता है. अगर इसे standard रूप से enable किया जाता है, तो अच्छा होगा कि कोई opt-out mechanism भी हो, ताकि जब इसकी आम ज़रूरत न हो, तब developers इसका उपयोग करने से बचें
      software development की बड़ी समस्याओं में से एक यह है कि developers को बेवजह complexity जोड़ने या अपनी cleverness दिखाने से कैसे रोका जाए. खासकर शुरुआती करियर वाले developers अक्सर किसी समस्या को सीधे, कम elegant और अधिक verbose तरीके से हल करके आगे बढ़ने की बजाय, समाधान को जरूरत से ज्यादा complex बना देते हैं
    • यह feature अभी थोड़ा जल्दी आया हुआ लगता है. आदर्श रूप से इसे lambdas और generic parameter packs आने के बाद आना चाहिए था
      अभी Go का generics support इतना परिष्कृत नहीं है कि यह उसे अच्छे से संभाल सके, इसलिए कुछ अजीब तरह की मजबूर सीमाएँ पैदा होती हैं
    • मैं भी इसे लेकर दुविधा में हूँ. inline functions पास करने की तुलना में यह lines of code भी कम नहीं करता
  • sql.Null[T] का जुड़ना अच्छा है. नए projects में मैं शायद इसका इस्तेमाल शुरू करूँगा
    अभी के काम में मैं sqlboiler के null [0] पर निर्भर हूँ, जिसका API काफी मिलता-जुलता है. यह sql.Null की तरह काम करता है, लेकिन इसमें एक अतिरिक्त IsSet() bool method है, जो बताता है कि value को कभी explicitly set किया गया था या नहीं, जिससे “intentional null” और “uninitialized होने की वजह से null” में फर्क करने में मदद मिलती है. अच्छा लगता है, लेकिन मैंने इसे व्यवहार में कभी इस्तेमाल नहीं किया

    • यह जानने की ज़रूरत कब पड़ती है कि null intentional है? database में तो इसका कोई corresponding type नहीं होता, है न?
  • standard library mux को फिर से देखने और शायद chi हटाने की संभावना को लेकर उत्साहित हूँ. ऐसी functionality का standard library में आना सच में अच्छा है

    • मैं भी यही कहने आया था. chi कुछ projects में शानदार रहा है, और इतना natural था कि उसके होने का एहसास तक नहीं होता था
      ऐसी functionality के standard library में आने का मतलब है कि यह हमेशा maintain रहेगी, और बहुत से Go programs में एक जैसा approach इस्तेमाल होगा
  • अगर production में Go का इस्तेमाल करते हैं, तो क्या आप लोग जल्दी से latest version पर चले जाते हैं, या पुरानी releases पर अटके रहते हैं?
    public projects को देखकर लगता है कि वे अक्सर comparatively नए features से बचते हैं. Generics न भी इस्तेमाल करें, तब भी मैं पुराने interface{} की जगह Go 1.18 में आया any इस्तेमाल करना चाहूँगा, और मैंने यह भी सुना है कि बाद वाला ज़्यादा “idiomatic” है

    • Square में हम आम तौर पर Go monorepo की default version बढ़ाने से पहले पहला point release आने का इंतज़ार करते हैं. अलग-अलग application owners चाहें तो पहले भी upgrade कर सकते हैं
      इस बार थोड़ी उलझन हो गई, क्योंकि Go टीम ने हमारे default को 1.21 पर बढ़ाने से पहले ही 1.22 जारी कर दिया. अब इंतज़ार करना लगभग convention बन चुका है, और Go releases का कुछ तोड़ देना बहुत कम होता है
    • नए features के लिए मैं तब तक इंतज़ार करता हूँ जब तक कोई अच्छी fit वाली problem न दिखे, लेकिन compiler version लगभग रिलीज़ के तुरंत बाद upgrade कर देता हूँ
      उदाहरण के लिए generics को वास्तव में इस्तेमाल करने से पहले मैंने लगभग 6 महीने इंतज़ार किया, ताकि उसकी usefulness, developer experience, और build/test speed पर असर देख सकूँ
    • काम पर, जो running containers हैं यानी SaaS/API services, उनमें developers freely latest builds पर जा सकते हैं
      लेकिन हम Go में end-user apps भी ship करते हैं, और वहाँ पुराने client OS के साथ compatibility के कारण 1.20 पर रहना पड़ता है. 1.21 में काफ़ी बड़ा cutoff था, इसलिए संभव है कि हम कुछ साल 1.20 पर ही रहें
    • CI, Go के latest container से build और test चलाता है, और test suite काफ़ी मजबूत है, इसलिए व्यवहार में यह लगभग auto-update जैसा है. अगर कुछ मेल नहीं खाता, तो pipeline टूट जाती है, और तब तय करते हैं कि आख़िरी working version पर pin करना है या breaking change ठीक होने तक update टालना है
      हर कुछ साल में एक बार नया version और third-party packages के बीच कोई subtle edge-case bug सामने आ सकता है, लेकिन परिभाषा के अनुसार ऐसे bugs test suite से बच निकलते हैं, इसलिए manual upgrade में भी शायद वे पकड़े नहीं जाते
    • मैं तो तुरंत upgrade कर देता हूँ
      अगर पुराने Go compilers का support चिंता का विषय है, तो पुरानी versions के लिए build conditions रखकर missing चीज़ें define की जा सकती हैं. उदाहरण के लिए, // +build !go1.7 के नीचे type any = interface{} रखा जा सकता है