8 ms·
Go 1.22
- kubb 3y agoRange over function is actually good. Now we can implement proper iterators for collections. In particular, it should be possible to have abstractions like clojure-style lazy sequences.
- nalgeon 3y agoIf you find the official release notes a bit dry, I've made an interactive version: https://antonz.org/go-1-22 https://antonz.org/go-1-22
- thatswrong0 3y agoThank you this is awesome. I find it so much quicker to read and understand things like this with examples.. and these are runnable / editable! Sick.
- justinclift 3y agoCool, that does help. It wasn't immediately obvious what the problem with the for loop sharing thing meant, but seeing it run and give unexpected results helped. :)
- drewlesueur 3y agoreally cool
- yeonsh 3y agoOh, it's great.
- scns 3y agoThe Compact and Replace examples leave me puzzled, are they correct?
- nalgeon 3y agoThey are correct. > Functions that shrink the size of a slice (Delete, DeleteFunc, Compact, CompactFunc, and Replace) now zero the elements between the new length and the old length.
- emmanueloga_ 3y agoFor those using Go for production, do you get to switch to the latest versions quickly, or do you get stuck in older releases? In the open a lot of projects seem to avoid newish features. I like to use `any` (from 1.18 ~ 2 years ago) where before we had to use `interface{}`, even if I'm not using generics (although I've been told the latter is more "idiomatic" :-/).
- mortallywounded 3y agoI switch right away. If you're worried about supporting older Go compilers, you could always have build conditions for older versions that define missing things like: // +build !go1.7 type any = interface{}
- mappu 3y agoAt my $DAYJOB devs are free to jump on latest builds for containers we operate (SaaS / API services). But we also deliver end-user apps with Go, and those have to stick to 1.20 for compatibility with older client OSes. 1.21 made significant cuts and so we will likely be on 1.20 for some years to come.
- drchase 3y agoWhich older OSes? The last 1.20 dot release was earlier today, some years from now it will be stale and probably insecure, though that matters less for internal apps than for internet-exposed ones.
- mappu 3y agoWindows 7, Server 2012, macOS 10.13 + 10.14, and so on. Together it makes up nearly 10% of our user base. We have a very slow-moving customer base and their choice of OS is out of our control. At this time last year there were still more Windows 7 users than Windows 11 in telemetry. Those old OSes are leaving security support, but actually Windows Server 2012 still gets updates from Microsoft (ESU) until 2026 so i'm surprised you dropped it already. Yes, Go1.20 will get insecure, but until that usage drops, not much can be done. Well, one thing: in the past, in order to maintain support for Server 2008, for a long while we built the app with both Go1.10 and Go1.(newer) and switched at install time. I don't recommend it! Every year was more difficult as the open source packages drifted away from compatibility and our build system had to still support GOPATH. Eventually we finally abandoned Go1.10!
- shakow 3y ago> "For" loops may now range over integers The future is now, old man!
- kristianp 3y agofor i := range 10 { What was the syntax for this before?
- tptacek 3y agofor i := 0; i < 10; i++
- kristianp 3y agoThanks. The new syntax emulates the python `for x in range(10):`.
- adtac 3y agoI must be getting old because I almost wish they didn't add this as it's slightly ambiguous whether it's ranging from [0, 10) or [1, 10] and anything ambiguous is probably going to haunt me at 3am some day
- cwbriscoe 3y agoI always just assume it is consistent to whether arrays start at [0] or [1] on whichever language I am working on.
- everybodyknows 3y agoInterestingly, this does not raise any error, rather has no effect. for i := range -10 { panic(i) }
- ctz 3y ago"yes, please run this loop minus 10 times" - statements dreamed up by the utterly Deranged
- candiddevmike 3y agoLooking forward to revisting the stdlib mux and possibly removing chi. I really appreciate seeing this stuff move into the stdlib.
- catherinecodes 3y agoCame here to say the exact same thing. chi has been reallly great for a couple projects--in fact, it's easy to forget it's even here. Moving them into the stdlib means they'll always be maintained and ensure that approach is used in many Go programs.
- omoikane 3y ago> In Go 1.22, each iteration of the loop creates new variables This was previously discussed here: https://news.ycombinator.com/item?id=33160236 https://news.ycombinator.com/item?id=33160236 - Go: Redefining For Loop Variable Semantics (2022)
- peter_l_downs 3y agoThe addition of `sql.Null[T]` is great. I'll probably start using that in new projects. In current stuff, I'm relying on sqlboiler's null [0] whose API is very similar — it works the same way as `sql.Null` will, but has an additional `IsSet() bool` method that tells you whether or not the value was ever explicitly set, to help you distinguish "intentionally null" from "null due to uninitialization". (Sounds nice, but I've never once used it.)
- eweise 3y agoCurious when you need to know when null is intentional or not. There's no corresponding type like that in the db.
- buzer 3y agoFor example when you are using partially populated record to update the database. If field is null intentionally it means it should be updated to it. If it's not set the update statement should not touch it.
- eweise 3y agoThanks. That makes sense. I don't have that pattern in my code but I can see that some might.
- peter_l_downs 3y agoThis is a great explanation. Sqlboiler allows you to send an update that will infer which values have changed and should be written — I bet that’s related to this. TIL!
- erik_seaberg 3y agoIt’s good to see them starting to make for-range loops work on user-defined ADTs.
- saclark11 3y ago> When io.Copy copies from a TCPConn to a UnixConn, it will now use Linux's splice(2) system call if possible, using the new method TCPConn.WriteTo. Interface upgrades, yet again, transparently giving us more zero-copy IO. Love how much mileage they’re able to get out of this pattern in the io package.
- lifthrasiir 3y agoGo standard library is absolutely littered with these kinds of tweaks. Not necessarily bad, but it does make an integration with non-standard library less satisfactory because such special casing is not scalable. Still within the expectation though.
- BillyTheKing 3y agoI've been mostly writing Typescript the past 3 years - and recently started writing code in Go. Initially I was a little apprehensive, lack of array functions, slightly less flexible type-system, etc. But after spending some time writing Go I now had to re-initialise a typescript project for a small-ish team (4-5 devs). The amount of time spent on things such as linting, selecting the correct library for server routing, the correct server, coding standards, basic error-handling and enforcing it with a custom error or Result type to get out of this nested try/catch hell which still loses the majority of errors. Setting up testing and mocking. Setting up Prisma and what not - and finally the PRs are still a hit and miss, some ok, some make use of weird JS functions.. Don't get me wrong, I really do like Typescript. But I gotta say after all of that it's just great using a language with a fantastic standard library, proper type-safety, with some coding standards built-in. It's obviously not without quirks, but it's pretty decent - and great to see that routing has now also moved into the standard library, another bit that you don't have to worry about - can't wait for some map/filter/find slice functions though!
- fennecbutt 3y agoYeah someone I know has been banging on about go, too. I have a personal project I want to do so maybe I'll pick go for it. The main pro and con to the JS ecosystem is the fact that it's so flexible; you can mostly do things how you want and there are so many libraries in each space all competing. But because you can do anything how you like it becomes hard to decide which library you want to use (or a diff one every project) and every dev has a different way of accomplishing the same thing. I used to write internal libraries and frameworks a lot in my career and one of my mantras was to use TS to try to lock devs into doing things a certain way but there only so far you can go. My main worry with Go is like, is everything built in? Are there multiple say, Web server libs like with nodejs or only a single option? How are deficiencies addressed if there are fewer options and fewer ways og doing things?
- leonheld 3y agoGo is beautiful, productive, readable. I love Go. It's my "C with niceties".
- KingOfCoders 3y ago
- KingOfCoders 3y agoI love how easy upgrading Go has become. Change 1.21.6 to 1.22.0 in your go.mod, done.
- konart 3y agoWhat does this have to do with upgrading? Your go.mod just specifies the minimum version you need to build the code. If you do not use new things available in in 1.22 your go.mod may have 1.21 (or even 1.13 if you are not using generics and can't be bothered with a few deprecated things. Like ioutil.ReadAll() which was deprecated since. 1.16)
- KingOfCoders 3y agoSorry not a native speaker. My understanding of "upgrading" a toolchain or dependecy in a project means, changing to a new version of the toolchain or dependency and make the project work again? With 1.22 memory consumption should be less and PGO has better performance from my understanding. When I change the minimum version in my project to 1.22.0 it will download 1.22.0 and use this for compilation. I would call that "upgrading" ~/Development/inkmigo$ go version go version go1.22.0 linux/amd64
- konart 3y agoNo need to be sorry. Not a native speaker either. I get your point. I'm just to used to the fact that Homebrew updates packages on the machine and services are build during CI\CD pipelines inside of a container.
- mseepgood 3y ago> What does this have to do with upgrading? Go automatically downloads the appropriate toolchain based on the version specified in a project's go.mod file. Once Go (>= 1.21) is installed on a machine, there is no need for manual updates anymore. https://go.dev/doc/toolchain https://go.dev/doc/toolchain
- xyzzy_plugh 3y ago
- moondev 3y agoStill holding out hope for a "go run" flag to easily run module programs with replacements in go.mod go run k8s.io/kubernetes/cmd/kubectl@v1.28.2
- deleted 3y ago[deleted]
- d0gsg0w00f 3y agoYes. Many times I've forgotten to remove my local "replace" in go.mod before git pushing. Would be nice to have a runtime replace for local dev.
- metaltyphoon 3y agoIf you use go.work (workspace) you don’t have to touch your go.mod file. Just don't commit go.work
- tommiegannert 3y ago> Enhanced routing patterns > This change breaks backwards compatibility in small ways, some obvious—patterns with "{" and "}" behave differently— and some less so—treatment of escaped paths has been improved. The change is controlled by a GODEBUG field named httpmuxgo121. Set httpmuxgo121=1 to restore the old behavior. That's a great enhancement now that the future of Gorilla Mux is shaky. But why doesn't that go against the Go 1 compatibility promise? > It is intended that programs written to the Go 1 specification will continue to compile and run correctly, unchanged, over the lifetime of that specification.
- zaphodias 3y agoUsually the Go team scrapes from GitHub and open source programs how people use something before breaking them; I suspect they found little usage of { and } in HTTP handler paths. They also provide a way of opting out the new behaviour, so they don't force you to change anything in your code (but yes, it does require you to set a new env var). The change to the for loop semantic is another example in this release; it effectively is a breaking change. All Go programs continue to compile and run, though with minor behavioural changes. I think Go took a pragmatic approach, and that was one of the reasons for its success.
- carstenhag 3y agoI don't see the point of using semver (or at least telling us about the same guarantees) and then not making use of it. If there were 10 breaking chances we should be at 11.x now, not at 1.x with 20 environment variables.
- bheadmaster 3y agoFrom a purist perspective, you're right - the contract has been broken, and a major version should've been incremented. However, Go has always been more of a pragmatic than a purist language. For example, they've analyzed tons of code and found that most of them had bugs caused by having `for` loop with a single variable being mutated. So they changed the `for` loop (in a technically backwards incompatible way) in order to make all those bugs disappear. In a way, they modified the formal contract to make it more aligned with the de-facto contract that users were expecting. I personally think that kind of pragmatism beats purism any day. Maybe the fact that I've never personally been affected by Go backwards incompatibilities also plays a role... But I've yet to find a single person who has :)
- divan 3y agoI've been writing Go for 9+ years, but for the last 4 years, I had to write a lot of Dart (for Flutter). I consider these two languages to be on the opposite sides of the complexity stance. Dart tries to add and implement every feature possible, but Go is the opposite. Two observations: 1) I'm spending a lot of time fighting multiple ways to init stuff in a class (i.e., declare the variable and set the value). Depending on the final/const/static/late prefix, there are multiple ways to init it in the constructor or factory or initState() method of Flutter's StatefulWidget, and god forbid you to refactor any of that – you'll be forced to rehaul all the initialization. Dart's getter feature (which makes functions look like variables) also adds confusion, especially with a new codebase. I constantly find it embarrassing how much time I need to spend on such a straightforward thing as variable/field initialization. I often find myself missing the simplicity of Go. 2) Compared to Go, Dart has all the juicy stuff like maps/streams/whatever for packing all in a single line. It's very tempting to use those for quickly creating singleliners with hard-to-understand complexity. Sometimes I even start feeling that I'm missing those in Go. But when I get to debugging those or, especially, junior developers looking at these write-only singleliners, with an array of ugly hacks like .firstWhereOrNull or optional '(orElse: () => null)' parameters, they are very confused, especially when cryptic null safety or type errors stops them. Rewriting those singleliners as a simple Go-style for loop is such a relief.
- doctor_eval 3y agoI agree, Go’s simplicity is the best thing about it. I think the same thing about ranges, I think I end up typing the same number of characters - but spreading it over three lines makes it feel “longer” than a comprehension like “forEach(f)”. But then I write the range longhand, and it’s no big deal. Speaking of initialisation though, I do wish Go had an idiomatic way to initialise struct fields to specific values. I don’t care about the lack of constructors; mostly, I just wish I could have bools initialise to true sometimes.
- divan 3y agoSure, it's always a tradeoff. Yet my pet peeve is that people rarely talk about the social aspects of the programming language. It's called "language" for a reason. We express our thoughts using this language ("I intend this code to do such and such"), and we expect other people to be able to understand what we intended, and we want to make sure that they understand exactly as we want them to. I judge languages on their ability to collectively construct mental maps in the brains of the developers who work on the same project. If they all read the same code, will they be able to understand the task and intent of that code without additional explanations? How cognitively hard would it be? Gottfried Liebnitz was obsessed with finding a Universal Language, which was exactly about this – making communication clear and lacking misunderstanding. I feel like Dart (and most other languages) approach is the opposite of that. Creating multiple ways to express the same intent is a sure go way to introduce misunderstanding and fracture the speakers of that language into dialects and groups. Go's, on the other hand, is really good at making this "reconstructing mental map" part a joy.
- doctor_eval 3y agoI’m super excited to see range over functions - iterators. It’s one of the only things I miss from Java. It took me a few reads to understand how the work, but in typical Go style (once I got it) it was so much simpler than the equivalent in most other languages I’ve used. Looking forward to it being promoted out of experimental.
- simiones 3y agoYou find func Backward[E any](s []E) func(func(int, E) bool) { return func(yield func(int, E) bool) { for i := len(s)-1; i >= 0; i-- { if !yield(i, s[i]) { return } } } } simpler than C#'s IEnumerable<T> Backward(T[] s) { for i := s.length-1; i >= 0; i-- { yield return s[i]; } } I think that's quite hard to defend, honestly. Granted, Java doesn't have anything comparable, so I'm not sure what you're comparing this feature to.
- doctor_eval 3y agoObviously your C# code is simpler; yes, I’m comparing to Java. I haven’t seen this style of iterator previously.
- simiones 3y agoCompared to implementing the equivalent Iterator in Java, yes, the Go code is much simpler. But there are better solutions than Go's in several other languages - C#, Python, TypeScript, C++, even in Rust (experimentally). They all use the same or very similar syntax to my C# sample above, and have the same semantics (plus or minus some details about memory allocation and exception safety). Go, as usual, came late to this party, and is being needlessly different and clunkier.
- usrbinbash 3y agoOn the risk of sounding like a massiv fanboy (which I, unashamedly, am): - Range over Integer - Direct support for methods and wildcards in the path directly in `net/http` - More free optimization - Improved tooling Sorry again for the fanboism, but Go really is the gift that just keeps giving :D
- mjw_byrne 3y agoPerhaps I'm a dinosaur but I don't like the range-over-function addition. I don't think it adds enough convenience to justify the complexity it adds to the language, and the functional style feels at odds with Go's explicit, imperative (albeit verbose) and feature-lean style, which I think was one of its major strengths. For the same reason I think the range-over-integer feature is a misstep. Go's lean feature set and minimal mental load have always been major strengths and differentiators of the language.
- lenkite 3y agoI also think this feature feels premature. Ideally, it should be introduced after lambdas and generic parameter packs. The Generics support in Golang is not sophisticated enough to support this at the moment leading to the strangely imposed limitations
- jjice 3y ago> Ideally, it should be introduced after lambdas Like syntactic sugar over `func`? Since func can already be anonymous and passed around just fine, I don't expect them to add additional syntax for functions.
- ericpauley 3y agoI'm ambivalent as well. It doesn't even save lines of code compared to passing an inline function.
- Cthulhu_ 3y agoSo at the moment this feature is optional / experimental and opt-in; if they make it standard on, I hope they add an opt-out mechanism of sorts, so that developers are discouraged to use it if it's not commonplace. I find that one big problem with software developers is keeping developers from adding complexity, or "flexing". Especially developers earlier in their career, present company included, tend to overcomplicate a solution instead of just solve the problem in a straightforward albeit inelegant and wordy fashion and move on.
- sitzkrieg 3y agodont get me wrong, i enjoy go and use it professionally with little complaints. but its kinda funny seeing several of the examples people used for go's pick-up-simplicity being added to the language, like generics and apparently generators etc. but im still fine with it as long as there is no extreme hidden logic on the level if operator overloading, crazy ctor chains, etc
- ihtkas 3y agoIs the memory issue reported in go 1.21 version in linux OS resolved in go 1.22? https://github.com/golang/go/issues/64332 https://github.com/golang/go/issues/64332