[HN Gopher] Go 1.21 Released
___________________________________________________________________
Go 1.21 Released
Author : Mawr
Score : 276 points
Date : 2023-08-08 15:28 UTC (7 hours ago)
(HTM) web link (go.dev)
(TXT) w3m dump (go.dev)
| badrequest wrote:
| I am really excited to start using the new structured logger.
| kiitos wrote:
| Even after seeing the API, which is enormous and wildly non-
| intuitive?
| cube2222 wrote:
| Could you expand what you mean?
|
| When skimming it I mostly saw the common API structure that I
| usually see in libraries / write myself when I need a logger,
| so I generally welcome the standardization.
| kiitos wrote:
| slog defines the concepts of
|
| - Logger -- created by New, accepting a Handler, providing
| a fixed set of level-based logging methods, asserting
| concepts of Attrs and Groups, not parameterizable by
| consumers
|
| - Handler -- with two default implementations, asserting
| concepts of Attrs Groups and Records, parameterizable by
| consumers as long as they follow the semantics defined by
| the interface
|
| - Attr -- arbitrary concept that maps to a k/v pair in a
| log record
|
| - Group -- arbitrary concept that namespaces a set of k/v
| pairs in a log record
|
| - Record -- arbitrary concept that requires a timestamp
| (expensive to compute), a level (one of a specifically
| defined enum which cannot be changed), and a PC stack
| pointer (obvious issues there)
|
| I've never seen a logging package which meets these
| requirements.
| badrequest wrote:
| I've seen the API, and it's not either of those things if
| you've already used a structured logger?
| iamcalledrob wrote:
| Yes!
|
| Logging always felt like something that (1) almost every
| project needs, and (2) there are too many 3rd party packages,
| with no "de facto" choice.
|
| This is particularly painful when working with 3rd party
| library code. There's a high chance that the consumer of
| library code uses a different logging package to the library
| author.
|
| Having structured logging in the stdlib is fantastic, because
| now there is a "go way" to this that libraries can use.
| eberkund wrote:
| Does this mean that all the third party logging packages will
| likely die out in the future? Or will they likely implement
| adapters to be compatible with the std interface?
| cratermoon wrote:
| From the original proposal <https://go.googlesource.com/pro
| posal/+/master/design/56345-s...>
|
| 1 "We expect existing logging packages to coexist with this
| one for the foreseeable future."
|
| 2 "We expect that this proposal's handlers will be
| implemented for all popular logging formats and network
| protocols, and that every common logging framework will
| provide a shim from their own backend to a handler"
| mdaniel wrote:
| seems the submissions for "Go $v Released" have been 50/50
| pointing to the doc url versus the blog url:
| https://go.dev/blog/go1.21
| ydnaclementine wrote:
| I'm a recent convert and enjoying it quite a bit for webdev.
| There's lots of books out there, but I found let's go and let's
| go further to be great project based books
| beeburrt wrote:
| I'm a recent convert as well. Thanks for the recommendation,
| I'll look them up.
| hwc wrote:
| I'm looking forward to the log/slog package. I might start
| switching over from our homegrown solution next week.
| lenkite wrote:
| No basic Map or Filter functions in the new slices pkg. Sadness.
| empath-nirvana wrote:
| I think it's a reasonable first pass at implementing generic
| functions.
|
| I'd love to see Map/Filter/Reduce, but starting with the
| simplest set of generic functions and getting people
| comfortable with them is probably a good idea.
|
| Go idiomatically is very imperative and introducing a new
| programming style at the same time as introducing generics
| might be too much change at once.
|
| I'd also like to see an option and a result type at some point
| so we can stop doing nil checks all over the place.
| morelisp wrote:
| If we're lucky they won't add them until they have some halfway
| decent fusion working in the compiler.
| masklinn wrote:
| Makes sense given the idea of getting some form of iterators
| support into the language, collection-specific HoFs means more
| duplication and worse composition as the intermediate
| collections generally need to be allocated on every step, and
| often can't be optimised away because you're stuck with your
| defined order of evaluation.
| febstar wrote:
| Seems to be the smallest Go release yet (at least since 1.4). I
| wonder how the binary size was reduced in the recent two
| versions? 1.21 63MB 1.20 95MB
| 1.19 142MB 1.18 135MB 1.17 129MB 1.16
| 123MB 1.15 116MB 1.14 118MB 1.13 114MB
| 1.12 121MB 1.11 121MB 1.10 114MB 1.9
| 98MB 1.8 86MB 1.7 78MB 1.6 81MB
| 1.5 74MB
|
| (linux-amd64 archives from https://go.dev/dl/)
| 38 wrote:
| Other two comments are wrong. The correct answer is that the
| compiler now builds everything on demand if it's not already
| built. This now includes the standard library as well.
| Previously built versions of standard library modules were
| being shipped.
| FiloSottile wrote:
| Long term intentional effort: https://go.dev/issue/27151
| tough wrote:
| All I could find for context about what caused it (which is
| not reflected in that issue)
|
| > Go command The directory $GOROOT/pkg no longer stores pre-
| compiled package archives for the standard library: go
| install no longer writes them, the go build no longer checks
| for them, and the Go distribution no longer ships them.
| Instead, packages in the standard library are built as needed
| and cached in the build cache, just like packages outside
| GOROOT. This change reduces the size of the Go distribution
| and also avoids C toolchain skew for packages that use cgo.
|
| https://tip.golang.org/doc/go1.20
| Someone wrote:
| Possibly compiler/linker improvements. For example, FTA:
|
| _"In Go 1.21 the linker (with help from the compiler) is now
| capable of deleting dead (unreferenced) global map variables,
| if the number of entries in the variable initializer is
| sufficiently large, and if the initializer expressions are
| side-effect free."_
|
| There also may be differences in debug symbols in the various
| binaries.
| candiddevmike wrote:
| Stuff keeps moving out of the standard lib related to crypto.
| First was PGP, now elliptic. Why doesn't Go want to provide
| stdlib crypto stuff?
| FiloSottile wrote:
| Go is absolutely committed to the cryptography standard
| library. What's happening is that we're deprecating legacy
| protocols and APIs to invest resources on packages that better
| align with the Cryptography Principles [0].
|
| In particular, crypto/elliptic was an unfortunate API that has
| been deprecated in favor of the new crypto/ecdh. Most
| applications can migrate (on their own time, as we don't break
| backwards compatibility even for deprecated packages) and get
| better security and performance. (A very small portion of
| applications might need lower level applications, in which case
| they can use third party modules based on the stdlib internals,
| like filippo.io/nistec.) You can read more on my Go 1.20 [1]
| and Go 1.21 [2] posts.
|
| [0]: https://golang.org/design/cryptography-principles [1]:
| https://words.filippo.io/dispatches/go-1-20-cryptography/ [2]:
| https://words.filippo.io/dispatches/go-1-21-plan/
| chrsig wrote:
| my bet is it has something to do with Filippo Valsorda having
| left google, but that's pure speculation on my part.
|
| https://github.com/FiloSottile
| FiloSottile wrote:
| Nope :) I'm still a maintainer, and actually happen to be the
| one that drove those two deprecations.
| https://words.filippo.io/full-time-maintainer/
| chrsig wrote:
| Glad to have my wild speculation disproven :) And glad that
| becoming a full time independent maintainer is working out
| for you!
|
| Though, in hopes you see this, I have to ask: Is there any
| sort of plan for if you wanted to step down from a
| maintainers role of the go crypto packages?
|
| You're sort of known as "the" go crypto person, so I guess
| it occurred to me that your bus factor might be quite high.
| Any thoughts you can give to assuage fears in that regard?
| Is there anything the community can do to share the load,
| short of becoming cryptography experts?
| kyrra wrote:
| Two reasons I can think of:
|
| 1) speed to update it in the case of a bug / security issue.
|
| 2) backwards compatibility.
|
| Getting a new Go release out is likely a lot more time
| consuming than bumping up the crypto library outside of there.
| And those libraries do not require full backwards compatibility
| compared to the Go standard library. So they can do breaking
| changes if need back without breaking the Go contract.
| eatonphil wrote:
| For 1) they create patch releases of Go versions fairly
| often. So I don't think that makes sense.
| mseepgood wrote:
| Perhaps they would prefer not to create them so frequently.
| h1fra wrote:
| adding min/max to a language made 10 years ago is kinda crazy
| when you think about it. Really looking log/slog package, it
| seems neat and was deeply needed.
| jakear wrote:
| Hah, I just went down a whole rabbit hole on super-logarithms
| and tetration wondering why you found it so critical as to
| warrant standard-library inclusion.
| thiht wrote:
| Note that min/max were already available in the math package,
| but they're a bit inconvenient to use (lots of casting to do)
| 015a wrote:
| The log/slog package is huge. I'm super happy to see them start-
| again to express opinions and solve more problem with just the
| standard library; and I hope to see more of it. This was Go's
| Thing at 1.0; you could build a production ready, large scale
| HTTP service with nothing but the standard library; and,
| probably, a structured logging package like Zap. Now; looks like
| we may not need it!
|
| If anyone on the Go team is reading this; thanks! And, as hacker
| news must always be the armchair commentator, if I may ask for an
| addition in go 1.22: encoding/yaml. Build it in. Go and YAML are
| the languages of devops, and I've written so many scripts with
| JSON as a configuration file only because Go has a JSON parser
| built-in, but not YAML.
| liggitt wrote:
| > if I may ask for an addition in go 1.22: encoding/yaml
|
| FYI, encoding/yaml was recently requested, and was declined in
| https://github.com/golang/go/issues/61023#issuecomment-16106...
| , for reasons I largely agree with.
|
| (I work for Google but not on Go)
| pojzon wrote:
| Im still looking for a language that will solve my biggest issue:
|
| - dependency hell..
|
| Recently had to update unmaintained project by 5 dependency
| versions higher. It was so painful with GO.
| ParetoOptimal wrote:
| I don't use Go a lot anymore, but I sometimes use Nix's
| buildGoModule:
|
| https://nixos.wiki/wiki/Go
|
| Oh wait... You mean because of breaking language changes?
| hu3 wrote:
| Vendoring might help with building old code. It stores a copy
| of depencies in a directory which you can include in git.
| https://go.dev/ref/mod#vendoring
|
| As for upgrading old libraries which might have broken
| backwards compatibility, I can't offer much.
| bananapub wrote:
| how would that help with building old code? is old code often
| unavailable upstream?
| randomdata wrote:
| Needing to change an entire dependency version (let alone four
| more versions) is a sign of human error.
|
| It is unlikely that software will fix a bumbling human. No
| matter how hard it tries, humans will always find some new way
| to do something stupid.
| adrianmsmith wrote:
| Re: https://github.com/golang/go/wiki/LoopvarExperiment
|
| I've mainly used Java which doesn't suffer from this particular
| problem. But I've often heard Java criticized on the grounds it
| captures values not variables, and that most other languages
| apparently capture variables. I remember learning Lisp at uni and
| being taught that it captured variables, for example.
|
| So do other languages suffer from this problem as well? How do
| they deal with it?
| assbuttbuttass wrote:
| In fact most languages suffer from this, but it's more acute in
| go because of how easy it is to create closures and threads.
|
| For example, what does the following Python code print?
| funcs = list() for i in range(10):
| funcs.append(lambda: print(i)) for f in funcs:
| f()
| mdaniel wrote:
| I didn't know the answer to this, but it seems like this
| actually behaves closer to `funcs.append("""print(i)""")`
| since funcs = list() for i in
| range(10): funcs.append(lambda: print(i))
| del i for f in funcs: f()
|
| actually NameErrors during f() so I don't think it is
| actually closing over the i as much as the i was left in
| scope and the code was seemingly lazy evaluated
| InfamousRece wrote:
| Right. In this example lambda does not capture i at all.
| You would need something like
| funcs.append(lambda i=i: print(i))
| germandiago wrote:
| prints all 9s.
| cutler wrote:
| It's called late binding and some Pythonistas actually
| consider it a feature.
| [deleted]
| dragonwriter wrote:
| > most languages suffer from this
|
| Specifically, I think, any language with closures where the
| loop variable exists in a scope enclosing all loop iterations
| with a value that is updated each iteration rather than a
| fresh variable in a scope local to each loop iteration has
| this problem.
|
| In Ruby this wouldn't affect idiomatic looping methods like
| #each, but would seem likely to affect the less-idiomatic for
| loop, which is built on #each but has the control variable in
| the surrounding scope. (Not 100% certain how it desugars
| though.)
| masklinn wrote:
| > In Ruby this wouldn't affect idiomatic looping methods
| like #each, but would seem likely to affect the less-
| idiomatic for loop, which is built on #each but has the
| control variable in the surrounding scope. (Not 100%
| certain how it desugars though.)
|
| I don't know how it desugars, but it is indeed affected
| when using `for...in`
| sharno wrote:
| Interesting, didn't think about closures in Python before. It
| seems that JS has the same behavior.
|
| Java forces you to final copy the variable.
| agumonkey wrote:
| I lost track of ES scoping rules but apparently `for (var i
| ...) { ... }` doesn't capture (legacy behavior) while `for
| (let i ...) { ... }` will.
| mdaniel wrote:
| I don't think that's limited to just `var`, as a `let`
| outside of the `for` will do the same
| let funcs = []; ;(() => { let i;
| for (i = 0; i < 10; i++) {
| funcs.push(function() { console.log('i=',i); })
| } })() for (let f of funcs) {
| f.call(null); }
|
| (I used an IIFE to hide the "let i" from the .call to
| ensure it wasn't late binding to the name like the python
| example did)
| agumonkey wrote:
| you think they have a special rule in `for (let .. of ..
| ) ... ` then ?
| kazinator wrote:
| In some cases, Common Lisp makes it implementation-defined.
| E.g. in (dolist (item list) ...) it is implementation-defined
| whether _x_ is a freshly bound lexical, or a stepped variable.
|
| In Lisp, you can easily write macros that have whatever
| semantics you want. You can easily write a _my-dolist_ which is
| like _dolist_ but freshly binds the item variable for every
| iteration, and next to it write a _my-dolist2_ which assigns a
| single variable.
|
| In languages like Go, the providers of your language provide
| all the syntax from behind a wall, and make these decisions for
| you. Knights in shining armor duke it out on the rooftop of an
| ivory tower, while lower vassals blog incessantly about the
| important work being done and decisions being made.
|
| By the way, MacCarthy's ancient Lisp (Lisp 1, Lisp 1.5) didn't
| have lexical scope, so it would not have made any difference
| whether each iteration stepped the variable with _setq_ or
| bound it with _let_. There would just be the one dynamic
| variable in all cases, not captured by any lexical closures
| (those being nonexistent). You 'd want to bind it at least once
| with _let_ so the prior value is restored when the loop is
| done.
|
| In Common Lisp, if we use a special variable as the loop
| variable, it likewise won't make a difference whether it is
| stepped or bound each time, since the binding isn't lexical.
| germandiago wrote:
| Macros is exactly what makes Lisp a one-man only language for
| every person unless you are really careful.
|
| That, combined with the fact that things are often poorly
| documented is what IMHO ruins the language ecosystem.
|
| I want to like Lisp and I love its interactivity but I find
| the language a bit more "construction material" language than
| a ready-to-use immediately language. What is bad about that
| is exactly what you mention: everyone will come up with a set
| of macros that others cannot fully grasp.
| kazinator wrote:
| A poorly documented and tested libraries will give you
| problems no matter what kinds of entities it defines.
| Someone who writes macros that nobody can easily grasp will
| also write functions nobody can easily grasp.
|
| If you have to reverse engineer someone's macros, you have
| all of the following going for you
|
| The macros run at compile time and then go away (unless the
| program is based on a dynamic compiling paradigm). They
| have no behaviors at run-time; their generated code does.
| No matter how complicated the macro, you can just run it
| and capture the output code, and through multiple examples
| get an understanding of what it's doing.
|
| If someone writes a buggered function, you may have to end
| up debugging it on a target system, perhaps an embedded
| one.
|
| The sky is the limit there. If it's a function in a kernel,
| you may have to debug some race condition between it, some
| interrupt handler and a piece of hardware.
|
| No such thing ever happens when debugging a macro itself.
|
| A macro doesn't interact with complex application state,
| because that doesn't exist. You never have to attach some
| gigabyte database and get some objects into the right state
| before reproducing some expansion problem in a macro. Code
| generated by a macro could be involved in a problem like
| that, possibly as a root cause, but tracing through the
| macro itself isn't.
|
| The people who write awful macros are usually not smart
| enough to do anything that is actually hard to understand.
| The problems you will find are lack of hygiene, multiple
| evaluations and such.
| germandiago wrote:
| > A poorly documented and tested libraries will give you
| problems no matter what kinds of entities it defines.
| Someone who writes macros that nobody can easily grasp
| will also write functions nobody can easily grasp
|
| Lisp makes this so easy to write macros and they have
| been promoted to be the "my-powerful-dsl-is-the-right-
| way-to-solve-a-problem" that, IMHO, it works actively
| against team work unless it is really well-dcumented.
| Now, mix that with the fact that code is not usually
| deeply documented and you get a cultural problem into the
| whole ecosystem.
|
| > A macro doesn't interact with complex application
| state, because that doesn't exist. You never have to
| attach some gigabyte database and get some objects into
| the right state before reproducing some expansion problem
| in a macro. Code generated by a macro could be involved
| in a problem like that, possibly as a root cause, but
| tracing through the macro itself isn't
|
| Tracing the macro can be as difficult as its expansion.
| If it gets obtuse it will add a lot of time to your
| workflow. I know they are powerful but it is probably the
| last feature I would use in a team, with a lot of care,
| and for trivial things or for really justified cases and
| with good documentation. If your code is full of macros,
| forget about readability, you threw it out through the
| window.
|
| > The people who write awful macros are usually not smart
| enough to do anything that is actually hard to
| understand. The problems you will find are lack of
| hygiene, multiple evaluations and such
|
| Because writing macros is not that simple in the first
| place. I find much easier to write regular code and use
| the well-known macros than grasp anonymous macro code.
| There are things you can only do with macros though, like
| lazy evaluation. But macros must be managed with extra
| care. For example, maybe instead of a macro it is better
| to use a higher order function with a closure to keep the
| code understandable than burying things in layers of
| macros.
| masklinn wrote:
| Note that there are two separate components to the issue:
|
| 1. the interaction between mutable locations and closures
|
| In most languages with mutable bindings, if you close over a
| variable you're closing over a "cell" and will see future
| modifications to it. This is the case in Go, Python, Ruby,
| Javascript, C#, ...
|
| A few languages avoid it e.g.
|
| - Java, not because it "captures values" but because it only
| allows capturing "final" variables so you can't update the
| bindings (you can still mutate in place when capturing
| reference types)
|
| - C++, because you have to specify the capture mode and it'll
| only be affected if you capture by reference (which you
| wouldn't do for a loop variable), so the likelihood of hitting
| this issue is pretty low
|
| - Rust, because even if you capture by reference you can't
| modify a binding with an outstanding reference
|
| 2. the scoping of loop variables, if you're capturing the loop
| variable but each iteration has a different version of the loop
| variable then you don't really mind too much, because each
| closure will capture its own loop variable, this doesn't fix
| the above issue but it does fix the most common occurrence of
| it
|
| That's what Go is doing, other languages which have done that
| are C# (when using a `foreach` loop), Javascript (when using
| `let` or `const` for the loop variable), ...
|
| Also Ruby, kind-of: using the `each` method for iteration is
| very common, and since then the loop variable is a parameter to
| the block it's basically a per-iteration local, "for...in"
| still has the issue. I guess C# also has that when using the
| linq ForEach method but I don't know how common _that_ is.
| munificent wrote:
| Probably worth pointing out that C# used to have Go's
| behavior and they changed it (a rare breaking language
| change) specifically because it was such a notorious pitfall.
|
| I think Go is doing the right thing here. I'm somewhat
| surprised they didn't always do this. (Dart has created a new
| loop variable for each iteration all the way back since
| before 1.0.)
| masklinn wrote:
| Similarly in javascript, "let" and "const" we're added
| specifically with block and per-iteration scoping, because
| the ever increasing popularity of callbacks for async was
| making the function-scoped var more infuriating every day.
| renewedrebecca wrote:
| How comfy is go for general native performance coding tasks?
| Basically looking for a C/C++ replacement. (I don't really like
| how Rust looks syntactically, and prefer GC over manual memory
| management.)
| stevemk14ebr wrote:
| Look into Nim or Zig instead if you're coming from C++
| germandiago wrote:
| I would also recommend to take a look at D.
| [deleted]
| kristianp wrote:
| If you're looking for the absolute top speed, it's not as fast
| as C++ or rust. Assembly functions can't be inlined, for
| example. But go allows you to control your memory structures
| and that gets you good cache utilisation, compared to, say
| java. Go is plenty fast enough for most applications.
| lytedev wrote:
| I'm not an expert at all, but I wouldn't. I would reach for nim
| or even zig before go. But it depends on what you're building,
| I'm sure!
| repeekad wrote:
| Personal experience is great, though for large projects C++ is
| definitely more robust.
|
| Really like how go handles parallelism and creating threads.
| germandiago wrote:
| I think Go is a really good fit to write async servers. Its
| set of features make it a killer language for that use case.
| assbuttbuttass wrote:
| I'm curious what are some of the reasons C++ is better for
| large projects?
| pjmlp wrote:
| As C replacement, I would say relatively ok, specially if you
| look at it from the point of view of Limbo in Inferno.
|
| As C++ replacement, I would stay is too lacking in features.
| For that I would rather reach out to C#, D, Java (with
| OpenJ9/Graal), or even Haskell/OCaml.
| KolmogorovComp wrote:
| > When printing very deep stacks, the runtime now prints the
| first 50 (innermost) frames followed by the bottom 50 (outermost)
| frames, rather than just printing the first 100 frames. This
| makes it easier to see how deeply recursive stacks started, and
| is especially valuable for debugging stack overflows.
|
| This is a very nice QoL improvement, I wish more languages made
| the change.
| michaeljx wrote:
| 100+ frames deep? I am a python dev, is that normal in Go?
| Sounds atrocious
| geodel wrote:
| Well its normal in Java and from what I have seen despite
| being advised against it a lot of folks coming from Java to
| Go have brought along Java style heavily abstracted code,
| framework first design patterns with them. This can
| definitely lead to very deep stack traces.
| masklinn wrote:
| Python will also do something like that, specifically it
| snips out repeated lines in self-recursive calls:
| https://github.com/python/cpython/issues/71010
| >>> a() Traceback (most recent call last):
| File "<stdin>", line 1, in <module> File "<stdin>",
| line 3, in a File "<stdin>", line 3, in a
| File "<stdin>", line 3, in a [Previous line
| repeated 894 more times] File "<stdin>", line 2, in
| a File "<stdin>", line 2, in b File
| "<stdin>", line 2, in c File "<stdin>", line 2, in
| c File "<stdin>", line 2, in c [Previous
| line repeated 97 more times] RecursionError: maximum
| recursion depth exceeded
|
| Sadly it's not smart enough to handle indirect recursion, so
| in those cases you get a thousand lines of garbage.
| eyelidlessness wrote:
| "This makes it easier to see how deeply recursive stacks
| started, and is especially valuable for debugging stack
| overflows."
|
| Mistakes are normal in any language. Debugging an infinitely
| deep recursion can be challenging in most.
| telotortium wrote:
| > Go 1.21 now defines that if a goroutine is panicking and
| recover was called directly by a deferred function, the return
| value of recover is guaranteed not to be nil. To ensure this,
| calling panic with a nil interface value (or an untyped nil)
| causes a run-time panic of type *runtime.PanicNilError.
|
| > To support programs written for older versions of Go, nil
| panics can be re-enabled by setting GODEBUG=panicnil=1. This
| setting is enabled automatically when compiling a program whose
| main package is in a module with that declares go 1.20 or
| earlier.
|
| An explanation of why this change was implemented is contained in
| the description of the implementing change, https://go-
| review.googlesource.com/c/go/+/461956. In short, calling
| `panic(nil)` before would make `recover` return nil, which is
| what's returned when there is no panic. `recover` doesn't have a
| `panicArg, ok = recover()` return value variant, so they fixed it
| this way.
| rcme wrote:
| Is it just me or is the new import initialization algorithm n^2
| in the worst case? Surprised by that.
| rickette wrote:
| The backwards compatibility promise (as always) is really nice.
| Java/JVM is the only other language/platform that I can think of
| that does more or less the same. Using both extensively by the
| way.
| mseepgood wrote:
| Yes, I like to build my castles on solid ground rather than on
| quicksand.
| germandiago wrote:
| C++ takes compatibility very serious. Though it has ABI stuff
| here and there you need to deal with due to its fully native
| AOT compilation nature.
| greggyb wrote:
| Common Lisp has been standardized for longer than Java's life.
|
| Also in the lisp world, Clojure has a fastidious dedication to
| backward compatibility.
|
| Perl 5 has maintained backward compatibility (though I am not
| certain if it is 100% compatible) by putting changes behind
| flags.
| beezlewax wrote:
| Pretty sure Rust has this too right?
| kiitos wrote:
| Rust is definitely not backwards-compatible in the sense that
| Go is backwards-compatible.
| stusmall wrote:
| How so? What breaking changes have you hit? It has the same
| guarantee and takes it extremely seriously. The only code I
| know of that compiled on a stable post-1.0 compiler but
| broke was because of bugs, even those cases are rare.
| kiitos wrote:
| I think std async is about as good an example as any.
| stusmall wrote:
| Do you mean async-std as in the 3rd party crate?
| predictabl3 wrote:
| Helloooooo riscv64-linux support! EDIT: lol this fickle site. Not
| my fault they didn't publicize the fact that they're now
| publishing riscv64 binary releases (allowing distros to bootstrap
| riscv64 targets now).
| mholt wrote:
| Not sure why you're getting downvoted. We got a pull request to
| add this to our Caddy build process today:
| https://github.com/caddyserver/caddy/pull/5720
| j16sdiz wrote:
| The "Loopvar" experiment looks like backward compatibility
| nightmare. As confusing as the existing behaviour could be, the
| new experiment is asking for trouble.
| kristianp wrote:
| For those wondering:
|
| https://github.com/golang/go/wiki/LoopvarExperiment
| tsimionescu wrote:
| The existing behavior is _extremely_ unlikely to be helpful,
| even accidentally. I will be shocked if anyone actually hits a
| problem related to this change. It may well fix more bugs than
| it introduces.
| philosopher1234 wrote:
| It's a breaking change, but rsc did very thorough testing of
| publicly available code and internal Google code and found
| essentially only bug fixes. But I think the risk is why this is
| an experiment and not a straight up change. Also, the new
| behavior would only be enabled on modules that are marked as Go
| 1.22 or above, not program globally, iiuc. So to me, this is
| very thoughtfully planned and unlikely to be any kind of
| nightmare
| [deleted]
| tapirl wrote:
| For `for-range` loops, it looks the benefits of this change are
| more than the drawbacks.
|
| For `for ...; ...; ...` loops, personally, I think the
| conclusion is the inverse.
|
| One breaking case: func main() {
| defer println() for counter, i := 0, 0; i < 3; i++ {
| defer func() { counter++ print(counter)
| }() } }
|
| It will print 111 when the change is made.
|
| More surprising cases:
| https://github.com/golang/go/issues/60078#issuecomment-15443...
| tedunangst wrote:
| Why don't any of the examples of surprise breakage link to
| real code relying this behavior?
| icholy wrote:
| C# did the same thing in 5.0
| https://ericlippert.com/2009/11/16/closing-over-the-loop-var...
| plorkyeran wrote:
| When C# shipped this change I was working on a large C#
| codebase and we were very worried about this. After auditing
| the entire codebase and checking every for loop, we found two
| pre-existing bugs in code which expected the 5.0 behavior and
| zero places which relied on the old behavior.
|
| Everyone that I've ever talked to who went through the
| transition has a similar story. In practice no one even
| incidentally relied on the old behavior. Go rolling it out as
| an experimental opt-in feature is a good idea, but it'll
| probably turn out to be unnecessarily cautious and they could
| have gotten away with just unconditionally enabling it.
| tapirl wrote:
| C# only did this on `foreach` loops, not on traditional `for`
| loops. Go plans to do this on both (`for-range` loops and
| traditional `for` loops).
| jjnoakes wrote:
| > no programs will change behavior due to simply adopting the
| new Go toolchain
|
| Seems like they thought about that. I think it's a good change.
| masklinn wrote:
| Is it? The experiment is just that, a way to test your packages
| for breakage, the proposition to opt in via langfile is similar
| to Rust edition systems which work fine.
|
| Way back when C# actually went through that change
| _unconditionally_ (LangVersion was not a thing yet), and there
| was barely any breakage.
| latchkey wrote:
| Forgetting to add `foo := foo` in a for loop tends to be bigger
| trouble. =)
| simonz05 wrote:
| Felix Geisendorfer did a bunch of work to improve continuous
| profiling performance [1].
|
| [1]: https://blog.felixge.de/waiting-for-go1-21-execution-
| tracing...
| aktau wrote:
| Indeed, this is awesome work.
| levischoen wrote:
| wow this was a very "we made everything a little better", lot of
| thanks to the golang devs
| WhereIsTheTruth wrote:
| > Go 1.21 improves build speed by up to 6%, largely thanks to
| building the compiler itself with PGO.
|
| Go already compile fast, and it still gets faster release after
| release, love it!
___________________________________________________________________
(page generated 2023-08-08 23:02 UTC)