[HN Gopher] Go 1.21 ___________________________________________________________________ Go 1.21 Author : pk2200 Score : 221 points Date : 2023-06-21 20:04 UTC (2 hours ago) (HTM) web link (go.dev) (TXT) w3m dump (go.dev) | silisili wrote: | These new packages, like slices and maps, were a long time | coming. So glad it's finally here. | | I cannot even begin to tell you how many different itemInSlice | functions I've written over the years. | throwawaygo wrote: | tbh whenever I write one of these it makes me wonder if I can | accomplish the same logic in a better way. | throwawaygo wrote: | Can we get arenas yet? | monocasa wrote: | Nice, my push for actually using the sha256 instructions on amd64 | finally got released. 3x-4x increase in hash speed on most x86 | which is really nice for content addressable storage use cases | like handling container images. | candiddevmike wrote: | Got a link to the PR? Curious to see how this is implemented. | jeffbee wrote: | It looks like https://go- | review.googlesource.com/c/go/+/408795 | xyst wrote: | Seems like these changes only benefit you if you have an | Intel processor. If you have an AMD or Arm processor, you | won't see any difference. | | Also, interesting to see assembly again after many years. | Haven't touched that since college during a compilers and | assembly course. | | Edit: never mind, amd has implemented these "sha-ni" | instructions since "Zen" [1] | | [1] https://en.wikipedia.org/wiki/Intel_SHA_extensions | monocasa wrote: | And adding that they already had support for ARM sha256 | instructions https://github.com/golang/go/blob/master/src | /crypto/sha256/s... | jeffbee wrote: | Huh, that is interesting how they do that. They are enabling | SHA instruction support based on CPUID and without respect to | the value of GOAMD64. I did not realize Go was doing that. | monocasa wrote: | AFAIK, the sha256 extension isn't a part of any of the x86_64 | microarchitecture levels, so a cpuid check is most | appropriate here at the moment. | jeffbee wrote: | Fair point. But what surprised me was the way HasAVX2 is | getting set. It is set on the hardware that has AVX2, even | if you set GOAMD64=v1. | als0 wrote: | In case anyone else was wondering what this is about, | here's some useful background | https://github.com/golang/go/issues/45453 | burntsushi wrote: | Yup, that's standard, including in other ecosystems. It's | what I do in ripgrep for example when your target is just | standard `x86_64` (v1). GNU libc does it as well. And I | believe Go has been doing it for quite some time. (The | specific one I'm aware of is bytes.Index.) | | This was especially important back before the days of | v1/v2/v3/etc of x86_64, since Linux distros distributed | binaries compiled for the lowest common denominator. So | the only way you got fast SIMD instructions (beyond SSE2) | was with a CPUID check and some compiler features that | let you build target specific functions. (And I'm not | sure what the status is of Linux distros shipping | v1/v2/v3/etc binaries.) | bbkane wrote: | I love the new stdlib additions- I've been pulling in these | dependencies since generics arrived and it'll be nice to have | them built-in. | cube2222 wrote: | I'm a bit surprised that the slog package was added to the | stdlib, but it does seem to use the API that I think is the most | ergonomic across libraries I saw in Go (specifically, varargs for | key values, and the ability to create subloggers using .With), so | I guess it's nice most of the community will standardize around | it. | | If all goes well, you won't have different libraries using | different loggers anymore, in some not too distant future, which | should improve easy composability. | resonantjacket5 wrote: | I think it's pretty exciting. Don't have to keep using regex or | weird parsing to get the key values from logs that one wants. | | Also a bit surprised how fast it was added to the stdlib, but | perhaps there was a lot more consensus on the api compared to | other golang proposals. | chrsig wrote: | I have mixed feelings about it. if nothing else, the | name..."slog" isn't exactly the word i want repeating to myself | as I'm working. | tomjakubowski wrote: | A little honesty is a good thing | vl wrote: | I wonder if it's possible to use slog in 1.20 already, is there | a back-port? | | I'm changing logging on the service right now and it just makes | sense to use it _now_ , but entire service can't move to pre- | release version of go. | onionisafruit wrote: | Indeed it's in "golang.org/x/exp/slog" | mdaniel wrote: | https://pkg.go.dev/golang.org/x/exp/slog#hdr-Levels seems | to fall into the same trap that drives me _starkraving_ | about the 18,000 different(!) golang logging packages: | there doesn't seem to be a sane way of influencing the log | level at runtime if the author doesn't have the | foresight/compassion to add a command-line flag or env-var | to influence it. A similar complaint about the "haha I log | json except this other dep that I import who logs using | uber/zap so pffft if you try to parse stdout as json" | fourseventy wrote: | I literally just updated all of my golang logging to use | zerolog so i could get severity levels in my logs. Bad timing | on my part! I guess ill re-do it all with slog, i prefer stdlib | packages to third party packages. | d1str0 wrote: | Tomorrow we will see a blog post titled "Why I always use 3rd | part dependencies instead of stdlibs" | philosopher1234 wrote: | ideally an slog handler is built for zerolog, so that you can | use slog BE and keep the zerolog FE | H1Supreme wrote: | The new built in functions for slice manipulation are a welcome | addition! | galkk wrote: | So copy-pasting min/max into every program isn't that a good of | an idea? | | I didn't like the way how opinionatedly those things were | presented in past and how silently/half baked (bolted in into | language) they are creeping their way in. Feels like somebody in | go team just had some spare cycles and decided to push that | thing. | | Yes, it's a bit funny to have another argument against people | whose position earlier was "yes, you can copy-paste max, not a | big deal, go is small language", but at the same time, it | should've been done much earlier. This is basic programming | language ergonomics, that go (still) lacks with many other | features. | openasocket wrote: | Glad to see the crypto performance improvements, I noticed a | major regression in the performance of some auth code with 1.20 | throwaway5959 wrote: | Why is map copy "dst, src" vs "src, dst"? | klodolph wrote: | Copy operations in Go are normally destination first, source | second. This includes builtins like copy() and library | functions like io.Copy(). Making it "src, dest" would make this | one case the opposite of all the others. | | Note that the order mimics variable assignment. You copy an | integer with: var src, dest int dest | = src // dest first, src second | | I appreciate the consistency. | Xeoncross wrote: | Thanks, "mimics variable assignment" is a good way to | remember it | thisarticle wrote: | Ah gotcha, thanks! | kinghajj wrote: | It's not that uncommon. | | https://en.cppreference.com/w/cpp/string/byte/memcpy | | https://en.cppreference.com/w/cpp/string/byte/strncpy | | https://en.wikipedia.org/wiki/X86_assembly_language#Syntax | synergy20 wrote: | really hope Go has something like MERN for node.js or Django for | Python, so I can use it for ready-to-go backend framework. There | are gin and echo etc, just not as widely adopted as MERN or | Django. | | in some of my use cases, I need make sure source code is fully | protected, neither Node nor Django can do that well, Go will be | perfect as it is compiled, however there is nothing like MERN or | Django in Go(yet). Another option will be Java, but I do not know | Java. | pizzafeelsright wrote: | Was there a push to get it released today? | racingmars wrote: | No, release candidate 2 was released today; Go 1.21 is not yet | released. | Hakkin wrote: | Huh, I'm glad to see generic Min/Max functions, but the fact that | they're built-ins is a little odd to me. I would have expected | them to put a generic math library into the stdlib instead. The | fact the stdlib math package only works with float64s has always | struck me as a poorly thought out decision. | tinco wrote: | What sort of use case do you see for non-float64 math | operations in a Go application? | tedunangst wrote: | Float32 is pretty popular in graphics. | klodolph wrote: | Making them builtins allows them to work as you'd expect with | cases like, func clamp(x float64) float64 { | return max(0, min(1, x)) } | | With ordinary functions, the arguments are assigned types too | soon, and you get integer types for 0 and 1 in the above code. | In C++ you might make the types explicit: | template<typename T> T clamp(T x) { return | std::max<T>(0, std::min<T>(1, x)); } | | That's not meant to be exactly the way you'd write these | functions, but just a little bit of sample code to show how the | typing is different. | Hakkin wrote: | That doesn't seem to be true, unless I'm misunderstanding | something. https://go.dev/play/p/ymM0tD3aGYg?v=gotip | | Obviously these sample functions don't take into account all | the intricacies of float min/max functions. | tjalfi wrote: | The proposal[0] gives a rationale. Using builtin functions lets | them be variadic without allocating a slice. | | [0] https://github.com/golang/go/issues/59488 | 29_29 wrote: | This is a big release. Lots of new packages. The language is | changing | benhoyt wrote: | It is a big release, and the number of new stdlib packages (4) | is relatively high for a Go release. That said, apart from the | addition of some minor builtins (min, max, clear), the | _language_ isn 't changing. That happened back in 1.18 with the | introduction of generics. | Karupan wrote: | _Release candidate_ | philosopher1234 wrote: | Seems like a really substantial release to me. The new built in | functions min, max, and clear are a bit surprising, even having | followed the discussions around them. The perf improvements seem | pretty great, I'm sure those will get much love here. | | Personally, I'm most excited about log/slog and the experimental | fix to loop variable shadowing. I've never worked in a language | with a sane logging ecosystem, so I think slog will be a bit | personally revolutionary. And the loop fix will allow me to | delete a whole region of my brain. Pretty nice. | saghm wrote: | Am I reading it correctly that `clear` does different things | for maps and slices? Why doesn't it remove all the items from | the slice like it does with the map, or set the values in the | map to the zero value like it does for slices? That seems like | an easy thing to get tripped up on | arp242 wrote: | You can't "remove all items from the slice"; you can only | change the length to 0: "slice[:0]". | anyoneamous wrote: | As a non-developer who has only gone as far as "hello world" in | Go, I'm baffled by the idea that the log/slog thing is new - | that seems like an absolutely basic language feature. TBH I'd | say the same about min/max, but could forgive those being | absent since Go isn't known for being numerically-focused... | tick_tock_tick wrote: | > that seems like an absolutely basic language feature | | Most languages have no logging "system" built in at all. | Honestly it's really quite rare. | ilyt wrote: | > As a non-developer who has only gone as far as "hello | world" in Go, I'm baffled by the idea that the log/slog thing | is new - that seems like an absolutely basic language | feature. | | Then you'd be even more surprised when you learn that the | vast majority of languages _do not_ have standard logging | library in core. | | Most have one or few common libraries that community | developed instead, but they are not in stdlib, and if stdlib | has one it's usually very simple one (Go had standard logger | interface that was _too_ simple for example) | anyoneamous wrote: | I have evidently been spoiled by Python and it's abundance | of batteries. | arp242 wrote: | There's been a "log" package since forever, but slog adds | structured logging with fields and some other things. I don't | think many standard libraries have that built in? | sa46 wrote: | Most languages include unstructured logging libraries in the | standard library, including Go. Structured logging is usually | provided by third party libraries. | metaltyphoon wrote: | The only other one I know would be C# with | Microsoft.Extensions.Logging. Its so ubiquitous that 3rd | party libraries work with its abstractions. Slog is a | really good thing for Go | ilyt wrote: | > The new built in functions min, max, and clear are a bit | surprising, even having followed the discussions around them. | | Was that discussion pre-generics? | | Most of functions and libraries introduced in Go 1.21 is stuff | people already put in community libraries (lodash being | probably most popular, despise utterly nonsensical name not | relating to anything it does) so it is just potentially cutting | extra dependencies for many projects. | tomjakubowski wrote: | You mean samber/lo? What is nonsensical about the name? | philosopher1234 wrote: | No, it was a recent discussion, here: | https://github.com/golang/go/issues/59488 | nasretdinov wrote: | I am honestly surprised nobody mentioned the intention of Go team | to make multipath TCP the default in later releases | kkirsche wrote: | Can you elaborate on why this is surprising for those who don't | fully understand the differences? | nasretdinov wrote: | I don't think Multipath TCP has been tested in enough | environments to become the default yet. It's compatible with | TCP, yes, but it's mostly useful for e.g. mobile devices that | have multiple links like Wi-Fi and 4G, and it lets users to | maintain TCP connection to a certain service even when moving | across networks. Go seems to be server-oriented first, and | there are some potential downsides to multipath TCP in a | datacenter environment (e.g. potentially higher CPU usage, | etc). | arp242 wrote: | "In a future Go release we may enable Multipath TCP by | default on systems that support it." | | This could be five years from now. Or maybe never. | ubavic wrote: | I enjoy Go so much. It is almost perfect language for getting | things done, but I still can't understand some design choices. | | Does someone knows why Go uses env variables (like GOOS and | GOARCH) instead command line arguments? | superb_dev wrote: | It could make it easier for build systems to be multi platform. | You don't have to keep track of custom args and add them to | every call, you can just set the environment once. | abalaji wrote: | I assume so that it can be sticky across invocations and is | easy enough to debug using `go env` | francislavoie wrote: | Env vars make it easier to automate in CI. The actual script to | build for each os/arch is the same but only the vars change. | It's convenient. You can always prefix the command with the env | vars on the same line if you want a one-liner. | Cthulhu_ wrote: | I guess so you can configure them on e.g. a build server | instead of tweak your build command, but then, neither is | particularly portable. | earthboundkid wrote: | An extremely generic release. | evacchi wrote: | GOOS=wasip1 is pretty cool IMO (disclaimer: I work on | wazero.io) | kernal wrote: | hiyo | [deleted] | candiddevmike wrote: | > New slices package for common operations on slices of any | element type. This includes sorting functions that are | generally faster and more ergonomic than the sort package. | | > New maps package for common operations on maps of any key or | element type. | | > New cmp package with new utilities for comparing ordered | values. | | Pun intended? =D | WhereIsTheTruth wrote: | > New built-in functions: min, max and clear. | | What a mistake.. reserved keywords are words I can no longer use | for myself... | | Zig does it better by requiring a prefix @ for most their builtin | needs | throwawaygo wrote: | _breaks all my variables named min and max_ | philosopher1234 wrote: | They're not reserved keywords. Existing/package defined min/max | functions would take precedence. They have the same semantics | as `append` | WhereIsTheTruth wrote: | You refactored your code, you think you wrote your ``min`` | function, but no, it'll call the builtin one, without warning | you.. | | I don't like this design.. | bananapub wrote: | if you have so few tests and so little code review that | this matters then I am not sure what to suggest | vito wrote: | The compiler will tell you if the types aren't compatible, | and this is only for primitive comparable types. What | `min()` implementation could you have that even does | something different? | KRAKRISMOTT wrote: | A heap? | Chiron1991 wrote: | Not too familiar with go toolchains, but I bet there's a | linter that will warn you about shadowing builtins. | dgfitz wrote: | Qt uses qMin and qMax, it may have been nice if go went | with like gMin and gMax | pjmlp wrote: | For anyone that misses their Objective-C days. | Dudester230602 wrote: | They did not expect a simple language created for faster | onboarding of graduates to catch on. Now that community is | pushing for features the language might evolve in strange | ways... | BarkMore wrote: | min and max are predeclared identifiers in the universe block, | not reserved words. | https://go.dev/ref/spec#Predeclared_identifiers | | You can continue to declare your own entities with these names. | panzi wrote: | Wait is this now heap allocating a value in every iteration of | every loop? I hope that allocation is optimized out in every case | where there isn't a closure over the loop variable? | doctor_eval wrote: | Regardless of how the compiler is optimising this, I 100% agree | that the old behaviour is unexpected and it's caught me at | least once. Really happy to see this (until recently) | unexpected change. | panzi wrote: | I don't actually use Go, but I have used many other languages | where it is like the old behavior. I learned once that I have | to build the closure correctly to get the value I want and | know now to do it. Don't have any statistics on whether I | made that mistake again, but anecdotally I can't remember a | case where I have. In their analysis they have found a lot of | cases with that mistake, though. So I guess fair enough. | | However, I wonder what it will mean if someone who mostly | writes Go will now use another language? Will they be more | prone to make that mistake? | collinvandyck76 wrote: | I didn't see this optimization when I read the overview. I also | hope that the compiler is smart enough to avoid this. | vbezhenar wrote: | Of course it'll be optimized. It's just semantics that's | changed. Compiler will make sure to copy variable value to new | address. | quacker wrote: | They discuss this here: | https://github.com/golang/go/wiki/LoopvarExperiment#will-the... | | In fact, you can enable warnings/logs that indicate whether | code that is affected by the loopvar experiment results in a | stack-allocated or heap-allocated loop variable: | https://github.com/golang/go/wiki/LoopvarExperiment#can-i-se... | | I imagine that the current workarounds for this issue also end | up with heap-allocated variables in many cases. | xh-dude wrote: | Generally it is optimized out. | | The fine details resemble the analysis of correctness - all the | evidence shows people expect per-iteration semantics with | considerable frequency, and don't rely on per-loop semantics | with measurable frequency. But it's impossible to completely | automate that assessment. Likewise, it's impossible to | automatically detect code that will spuriously allocate because | of the semantic transition. | throwawaygo wrote: | So I guess with new builtin functions we will be breaking | backwards compatibility? | racingmars wrote: | If you already have your own functions or variables named max, | min, or clear in-scope, they will shadow the new built-in | functions and your code will continue to use your own version | of the functions. No breakage to existing identifiers that | match the new function names. | | (This is the same behavior as the append built-in function | today, for example. These things in Go are _not_ reserved | keywords, they are simply global functions that can be | overridden at other scopes.) | metaltyphoon wrote: | Lets be honest, its a terrible choice | racingmars wrote: | In what way? Overall as a language, identifier shadowing is | a feature of the language in nested scopes. Are you saying | built-in identifiers (that aren't language keywords) should | be treated specially and work differently than user- | declared identifiers? | w10-1 wrote: | Overall, a release more for engineering than language. Even the | new API's are mainly optimizations, and optimizations are netting | ~10% (pretty good for an mature toolset). | | The WASI preview shows Google is committing engineering resources | to WASM, which could grow the community a touch. | Cybergenik wrote: | Wrote a blog explicitly asking for some of these changes last | year: https://www.lremes.com/posts/golang/ | | Nice to see their going in a good direction. | colesantiago wrote: | Hmm. | | Not really an interesting Go release here unless I am missing | something. | | Has Go peaked already? | Cthulhu_ wrote: | What big thing are you expecting? Go is more of a stable | language, a reliable and boring language for building software | now that in ten years you can still maintain. Go isn't peaking, | Go isn't an exciting or cool or hype language, it's just... | there. And that's just fine. | | Too many languages just started borrowing features from others, | saying "yes" to every suggestion, until they got out of control | and all over the place. Go says "no" more often than not. Which | isn't always a good thing, mind; generics took a long time | because they wanted to understand the problem and not add more | like what happened to Java. The builtin min/max features up | until this release only supported float64. Lots of small | annoyances like that. | jjice wrote: | > ...generics took a long time because they wanted to | understand the problem and not add more like what happened to | Java | | Just out of curiosity, can anyone regale me with that history | with Java's generics? | jrockway wrote: | "type erasure" is the search term you're looking for. | nu11ptr wrote: | It is interesting to see them add things like the "clear" | function for maps and slices after suggesting to simply loop and | delete each key one at a time for so long. Is this a result of | the generics work that makes implementation easier vs. the extra | work of making a new "magic" function (like "make", etc.)? | skybrian wrote: | From the spec [1], it was because the loop doesn't work to | clear a map with a NaN key. | | [1] https://github.com/golang/go/issues/56351 | Waterluvian wrote: | It might also be that they've worked their way down the | priority list and are getting to these features that are | largely just to tidy up code. | stefan_ wrote: | Clearing a container is usually a much simpler and faster | operation than looping through all and removing them | individually. That's not a question of tidying something up. | onionisafruit wrote: | There were compiler optimizations for clearing by | iterating. I haven't looked at the code, but I suspect this | won't be much more efficient than iterating was with the | optimizations. | alex_lav wrote: | > It is interesting to see them add things like the "clear" | function for maps and slices after suggesting to simply loop | and delete each key one at a time for so long. | | Slowly walking back dogmatic positions is just how the Go team | works. | | I say this as a person that wrote Go full time for a handful of | years. | maximilianburke wrote: | That `clear` on a slice sets all values to their type's zero | value is going to be extremely confusing especially coming from | other languages (Rust, C#, C++, Java, ...) where the same-named | function is used on list-ish types to set their length to zero. | | Doubly-so when `clear` on a map actually seems to follow the | convention of removing all contained elements. | neonsunset wrote: | C#'s array/span.Clear() does exactly the same - it zeroes | them out. | klodolph wrote: | Sure, although as a Go user, the behavior described is | exactly what I'd expect. These new functions are no different | from functions that you could write yourself. | Jabbles wrote: | The builtin clear() will handle cases like deleting NaN | from a map. | maccard wrote: | I'm a go user, and think it's dumb that: | clear(f) fmt.Println(len(f)) | | will have different results if f is a slice and a map. | 6D794163636F756 wrote: | It sounds like they're inheriting the naming from the calloc | command. Allocates then 0's the memory. It lines up with the | go devs' backgrounds | philosopher1234 wrote: | One aspect of this is that it was formerly impossible to delete | NaNs from a map[float64]T, unless you had the nan already. | djsavvy wrote: | The new experimental fix for loop variable capture [0] is huge; | this is the biggest footgun with the language in my experience. | | I hope the experimental fix makes it into the next version of Go | by default. | | [0] https://github.com/golang/go/wiki/LoopvarExperiment | showdeddd wrote: | I wonder if the new stdlib logger is featured enough to get rid | of logrus/zerolog. | JyB wrote: | I'm wondering the same. Anyone already played for some time | with the pkg? | richieartoul wrote: | I've been using it for a few weeks now. Overall pretty happy | with it. Has good default API, and can be basically | arbitrarily extended as needed. We even have a custom handler | implementation that allows us to assert on specific logs | being emitted in our stress/fuzz testing. ___________________________________________________________________ (page generated 2023-06-21 23:01 UTC)