LWN: Comments on "Go 1.22 released" https://lwn.net/Articles/961196/ This is a special feed containing comments posted to the individual LWN article titled "Go 1.22 released". en-us Mon, 22 Sep 2025 01:48:11 +0000 Mon, 22 Sep 2025 01:48:11 +0000 https://www.rssboard.org/rss-specification lwn@lwn.net Go 1.22 released https://lwn.net/Articles/961795/ https://lwn.net/Articles/961795/ mathstuf <div class="FormattedComment"> <span class="QuotedText">&gt; suggesting that we all need to use 'map', 'filter' and 'reduce' functions and complicated iterator schemes.</span><br> <p> Because these functions separate the "what" from the "how" nicely. I don't have to seek out an extra or missing `!` or half-done modus ponens bug hidden in an `if` condition and change my thoughts based on whether the body contains `break` or `continue`. Instead, I get `until`, `while`, or `filter` as a name. Are we mutating the container? The values? Building a new structure or just making a pass over it? These are the kinds of questions Rust's `Iterator` trait methods answer for me directly. Then I can focus on *what* the code is doing overall without having to squint through a haze of partially-remembered open-coded intro-CS-course algorithm loops.<br> <p> C++ also does it OK, but they don't compose all that well. Ranges does better but I've not had the chance to use them in anger yet.<br> </div> Mon, 12 Feb 2024 13:15:47 +0000 Go 1.22 released https://lwn.net/Articles/961688/ https://lwn.net/Articles/961688/ Cyberax <div class="FormattedComment"> Yep, it's extremely frustrating when you get something like "IO error" in your logs without any details or a stacktrace. Go has finally grown a standardized way to wrap errors, so you can somewhat easily preserve the chain of failures like this: "failed to call func1 -&gt; failed to open HTTP connection -&gt; failed to resolve DNS name -&gt; IO Error".<br> <p> Now Go needs to work to make it more idiomatic.<br> </div> Sat, 10 Feb 2024 20:37:40 +0000 Go 1.22 released https://lwn.net/Articles/961686/ https://lwn.net/Articles/961686/ mathstuf <div class="FormattedComment"> <span class="QuotedText">&gt; I'm talking about `if (err != nil) {return nil, err;}` statements that can easily take up half of all the code in functions that call a lot of other functions. They are unergonomic, and they prevent chaining.</span><br> <p> This is bad anyways. Making sugar for bad idioms will only rot your teeth (same as blind `?` error bubbling in Rust). What is missing is the context that made the error happen. I find "file not found" from a high-level API useless. "Git repository expected; no .git found" is actually useful. Better as an enum so that code can inspect and adapt instead of low-level code assuming that a pre-baked string for user consumption is the only suitable representation.<br> </div> Sat, 10 Feb 2024 15:43:46 +0000 Go 1.22 released https://lwn.net/Articles/961601/ https://lwn.net/Articles/961601/ Cyberax <div class="FormattedComment"> Can you point out a couple of recent examples? Zig essentially uses algebraic types, same for Rust, Go uses multiple return values, even C++ is also adding algebraic types for error handling.<br> </div> Fri, 09 Feb 2024 16:17:55 +0000 Go 1.22 released https://lwn.net/Articles/961597/ https://lwn.net/Articles/961597/ michaelkjohnson <div class="FormattedComment"> So-called "Exceptions" as used in many languages that conflate (expensive) exceptions with (cheap) normal errors are not a thing at all in Go. Instead, Go has a panic/recover system and an error system.<br> <p> The Go "Error" type is an interface that fits into Go's normal type system:<br> <p> <a href="https://go.dev/blog/error-handling-and-go">https://go.dev/blog/error-handling-and-go</a><br> <p> For an understanding of panic and recover, see:<br> <p> <a href="https://go.dev/blog/defer-panic-and-recover">https://go.dev/blog/defer-panic-and-recover</a><br> </div> Fri, 09 Feb 2024 15:55:30 +0000 Go 1.22 released https://lwn.net/Articles/961541/ https://lwn.net/Articles/961541/ farnz <p>Out of interest, are they avoiding the two big problems I have with legacy exception-based languages: <ol> <li>It's impossible at the call site in (at least) Java, C++ and Python to see whether a given call might throw an exception; I have to look at the function signature in Java or C++ to see if there's a suitable "noexcept" type marker (or lack of a list of exceptions, in Java's case). This one bites me regularly, since I get people showing me their code that's failing, and telling me that it can't fail in that way - inevitably, when I get a backtrace out of them, it shows that they're calling something that's throwing an exception when they thought they were calling something infallible. <li>Maintaining checked exception specifiers is a chore for mid-level libraries (it's fine if you're a foundational library like the standard library); I can't just say "my exception specifier is that of <tt>readFoo</tt> plus that of <tt>parseRecord</tt> plus my own exception type", but I have to go and see what the exception specifiers of those functions are and copy-and-paste it across. And every time their exception specifiers change, I have to see if that affects me or not - can I remove a no-longer-needed specifier, do I need to add a specifier? </ol> Fri, 09 Feb 2024 14:27:27 +0000 Go 1.22 released https://lwn.net/Articles/961495/ https://lwn.net/Articles/961495/ farnz <p>The point of brevity in a programming language is to make doing the right thing easier than doing the wrong thing. If my "happy path" (the path I take if there are no errors) is hidden away in a sea of error handling, then it becomes hard to see whether or not the happy path does the right thing, because I've got to read my way around the error handling in order to actually see the happy path. <p>If you come up with a simple way to do the right thing, people will use it. Else, you have to keep an eye out for accidental mistakes - e.g. typing <tt>fooR, fooE := getFoo(); if fooR != nill { return fooE; };</tt> sort of thing, where I'm using <tt>;</tt> to mark newlines. Fri, 09 Feb 2024 10:34:36 +0000 Go 1.22 released https://lwn.net/Articles/961498/ https://lwn.net/Articles/961498/ taladar <div class="FormattedComment"> Shorter is better if shorter means you can see at a glance that the hundreds of copies of identical code are actually identical instead of having 99 identical copies and one that is different.<br> </div> Fri, 09 Feb 2024 10:17:52 +0000 Go 1.22 released https://lwn.net/Articles/961473/ https://lwn.net/Articles/961473/ quotemstr <div class="FormattedComment"> <span class="QuotedText">&gt; the modern consensus is that exceptions are a bad idea</span><br> <p> No it isn't. There's a small, vocal community that says so, but that doesn't make it right, and there are plenty of new exceptional systems being made.<br> </div> Fri, 09 Feb 2024 05:46:08 +0000 Go 1.22 released https://lwn.net/Articles/961430/ https://lwn.net/Articles/961430/ Cyberax <div class="FormattedComment"> New handling will (likely) just add a shortcut for the old idiomatic code. Nothing will change behind the scenes, the old code will still be perfectly fine.<br> <p> It might eventually start _looking_ strange to new Go developers, but that's already true for other kinds of code. For example, very old Go code had no `context.Context` (so it was not interruptible) and even used "goto err" pattern (see: <a href="https://cs.opensource.google/go/x/net/+/master:websocket/client.go;l=81">https://cs.opensource.google/go/x/net/+/master:websocket/...</a> ).<br> </div> Thu, 08 Feb 2024 21:29:53 +0000 Go 1.22 released https://lwn.net/Articles/961429/ https://lwn.net/Articles/961429/ Cyberax <div class="FormattedComment"> I'm toying with writing a simple pre-compiler to try and translate "?" into "if err != nil...". This is really easy, because Go doesn't use "?" right now for anything (there's no ternary if) so the grammar will stay unambiguous.<br> <p> I tried some manual experiments, and the resulting code looks _so_ _much_ _more_ _readable_.<br> </div> Thu, 08 Feb 2024 21:21:03 +0000 Go 1.22 released https://lwn.net/Articles/961423/ https://lwn.net/Articles/961423/ milesrout <div class="FormattedComment"> Because shorter is not necessarily better, and syntactic sugar is not automatically good. Brevity is the soul of wit, but it is not the soul of programming. It's more stuff to learn, and the language is already general purpose. It doesn't need an extra way of doing something it can already do! You are conditionally returning from a function. That's simply described: a conditional return. So conditionally (if) return (return). That's how programming works. You don't need syntactic sugar for every combination of control operators you think up.<br> </div> Thu, 08 Feb 2024 20:27:33 +0000 Go 1.22 released https://lwn.net/Articles/961422/ https://lwn.net/Articles/961422/ milesrout <div class="FormattedComment"> What's markedly substandard for LWN is Cyberax's notorious and unending trolling.<br> </div> Thu, 08 Feb 2024 20:24:44 +0000 Go 1.22 released https://lwn.net/Articles/961420/ https://lwn.net/Articles/961420/ milesrout <div class="FormattedComment"> That's not the argument at all. The argument is that they shouldn't "fix" it because it's not broken in the first place. <br> </div> Thu, 08 Feb 2024 20:23:24 +0000 Go 1.22 released https://lwn.net/Articles/961315/ https://lwn.net/Articles/961315/ michaelkjohnson <div class="FormattedComment"> Fair! You might even say that the pattern encourages developers to raise errors as panics when implement chaining; an anti-pattern.<br> <p> (It's also possible to embed errors instead and have explicit handling in chains, so they don't exactly *prevent* chaining, but I agree that it is reasonable to argue that this is not the ergonomic best implementation of chaining.)<br> <p> So my complaint isn't related to your concerns, and I appreciate the clarification!<br> </div> Thu, 08 Feb 2024 14:13:47 +0000 Go 1.22 released https://lwn.net/Articles/961316/ https://lwn.net/Articles/961316/ farnz <p>And given that this is a common pattern in existing Go code, why not have a special syntax that implements this form of error handling for you? Something that converts: <pre> <code> varFoo, err := GetFoo() if err != nil { return err } </code> </pre> into a shorter form - like <tt>varFoo := GetFoo() orReturnErr</tt>, maybe using a sigil for <tt>orReturnErr</tt>? Thu, 08 Feb 2024 14:06:44 +0000 Go 1.22 released https://lwn.net/Articles/961311/ https://lwn.net/Articles/961311/ georgm <div class="FormattedComment"> <span class="QuotedText">&gt; Because it's ugly and unidiomatic</span><br> <p> The "ugly" depends on personal preference.<br> <p> Now with type "any" - you have that split already. Or should we continue using interface{} all over the place to not have new and legacy code? And generics?<br> <p> <span class="QuotedText">&gt; You use the same simple mechanisms for everything. Go is particularly good about this, almost as good as C</span><br> <p> Yes, as good as C to not bring any safety measures or syntax help:<br> You need a map: use map[foo]bar<br> <p> Wait? You have to "make(map[foo]bar)" (or map[foo]bar{}) before using it (but slices are okay to not exist, simple).<br> <p> Wait? You want to use it in parallel go routines (not even in our code, but for example the http router)? Don't use it. It is unsafe, or (like in general in go) - add a separate lock to use it.<br> <p> But you could use sync.Map for this. But then forget about the types (even if go supports generics by now).<br> <p> Simple might be too simple or too error-prone. No one is hindering you on using this and nobody complains (until something crashes).<br> <p> Just one example of "simple". There are a lot of other rough "simple" edges.<br> <p> </div> Thu, 08 Feb 2024 13:35:05 +0000 Go 1.22 released https://lwn.net/Articles/961312/ https://lwn.net/Articles/961312/ Funcan <div class="FormattedComment"> It's not "we can never fix anything" and more "we take old cold into account when making a decision whether to fix something, and we weight the value of keeping old choice idiomatic fairly heavily".<br> <p> There's the change in this release for variable reuse in for loops, which removes the need for an ugly idiom in new code, but which will have to stay in coffee intended for older compiler versions, for example.<br> <p> Adding genetics also meant that some old code became less idiomatic, but it was considered a big enough win.<br> </div> Thu, 08 Feb 2024 13:25:48 +0000 Go 1.22 released https://lwn.net/Articles/961309/ https://lwn.net/Articles/961309/ Cyberax <div class="FormattedComment"> <span class="QuotedText">&gt; The amount of nonsense spewed over Go's excellent choice to disambiguate errors (via the type system) from exceptions (panic) continues to amaze me.</span><br> <p> I'm not talking about panics, the modern consensus is that exceptions are a bad idea. Go has some strange ideas about `recover`, but whatever, it's at least reasonable.<br> <p> I'm talking about `if (err != nil) {return nil, err;}` statements that can easily take up half of all the code in functions that call a lot of other functions. They are unergonomic, and they prevent chaining.<br> </div> Thu, 08 Feb 2024 13:21:41 +0000 Go 1.22 released https://lwn.net/Articles/961307/ https://lwn.net/Articles/961307/ Cyberax <div class="FormattedComment"> <span class="QuotedText">&gt; Because it's ugly and unidiomatic, or it renders existing code unidiomatic.</span><br> <p> This argument is as stupid as anything. "We can't fix stuff because fixing stuff would make our old stuff look bad". So there.<br> <p> </div> Thu, 08 Feb 2024 13:15:04 +0000 Go 1.22 released https://lwn.net/Articles/961304/ https://lwn.net/Articles/961304/ michaelkjohnson <div class="FormattedComment"> The amount of nonsense spewed over Go's excellent choice to disambiguate errors (via the type system) from exceptions (panic) continues to amaze me.<br> <p> This is, for example, something that Python got fundamentally wrong (see os.exists and the many wrappers written to not take the expensive exception case for file does not exist, which is properly neither an error nor an exception), and when I learned Go I was delighted that Go did not perpetuate this particular class of design error.<br> <p> Go error handling is an example of the finely-tuned design sense that its creators brought to the language.<br> <p> Explicit is better than implicit, and errors are not exceptions. Anyone who thinks errors are exceptional hasn't been paying attention. ☺<br> </div> Thu, 08 Feb 2024 13:14:06 +0000 Go 1.22 released https://lwn.net/Articles/961305/ https://lwn.net/Articles/961305/ timon <div class="FormattedComment"> Oh come on, this comment is markedly sub-standard for LWN.<br> </div> Thu, 08 Feb 2024 13:09:38 +0000 Go 1.22 released https://lwn.net/Articles/961297/ https://lwn.net/Articles/961297/ milesrout <div class="FormattedComment"> Of course. You're right, we should just replace it all with WASM or something right? &lt;/eyeroll&gt;<br> </div> Thu, 08 Feb 2024 12:28:07 +0000 Go 1.22 released https://lwn.net/Articles/961295/ https://lwn.net/Articles/961295/ milesrout <div class="FormattedComment"> Because it's ugly and unidiomatic, or it renders existing code unidiomatic. It means there are two ways of doing things where before they was just one. Either that creates inconsistency, or people pick one or the other as the "preferred" or "best practice" way of doing things - and then it means you separate the world into "old legacy" code and "new" code. This has lots of unfortunate flow-on effects. For example, it would encourage people to rewrite existing code to be more "modern" (for no good reason - the old code works fine). But it's also just distasteful. The nice thing about 'Go' is that code ages pretty gracefully compared to languages that constantly churn new syntactic sugar/library sugar into the language. C++ is notorious for this: you can pretty much tell what year some C++ code was written as soon as you look at it, once you know what to look for. 'Oh yeah, make_shared but it's still using make_unique, that's likely to be 2014ish'. <br> <p> I think the worst part of it, though, is that it creates special-case syntax for what is should just be general programming. Go supports multiple return values and sometimes those return values include errors. Sometimes they don't. The nice thing about programming languages is that they are general. You use the same simple mechanisms for everything. Go is particularly good about this, almost as good as C. In C, almost _everything_ you do is arithmetic, dereferencing, taking the address of something, for/while/if/switch or calling a function. In Go you can add '&lt;-' and 'go'. <br> <p> Why add new syntax to do something that is so simply achieved with a simple 'if' statement? It reminds me of people suggesting that we all need to use 'map', 'filter' and 'reduce' functions and complicated iterator schemes. Do we? What's wrong with a 'for' loop with a nested 'if' structure controlling a line of code that modifies a variable? More than sufficient, I think. Just to save a few characters? Making code more dense isn't necessarily a good thing. Error handling in Go gives your code a nice bit of breathing room, I think. Code in more dense languages just needs more blank lines to space it out, IMO. <br> <p> Basically, I think syntactic sugar is generally bad.<br> </div> Thu, 08 Feb 2024 12:26:52 +0000 Go 1.22 released https://lwn.net/Articles/961293/ https://lwn.net/Articles/961293/ georgm <div class="FormattedComment"> Why not add syntactic sugar for the most used pattern in go (lending from rust syntax):<br> <p> if function returns "(foo, error)" or just "error":<br> a "?" on a function which returns (bar, error) would return (default, error) or only error on error<br> example: file := os.Open("file.txt")?<br> a "?" on a function which return only error woud return (default, error) only error on error<br> example: os.Mkdir("testdir", os.ModePerm)?<br> <p> You are not forced to use this pattern, so both the current and the new style would be fine and can coexist<br> </div> Thu, 08 Feb 2024 11:58:44 +0000 Go 1.22 released https://lwn.net/Articles/961271/ https://lwn.net/Articles/961271/ pj <div class="FormattedComment"> <span class="QuotedText">&gt;Not only is there no better way of doing it,</span><br> <p> [citation needed]<br> <p> ...for instance, I think Zig does it better, though in the end it's a matter of opinion.<br> </div> Thu, 08 Feb 2024 01:47:30 +0000 Loop variables shared between iterations - not just in Go https://lwn.net/Articles/961261/ https://lwn.net/Articles/961261/ iabervon <p>That looks less odd than what I'd have thought of, which is:</p> <pre>[(lambda i: lambda: i)(i) for i in range(10)] </pre> <p>But I think I prefer:</p> <pre>def make_callback(i): return lambda: i [make_callback(i) for i in range(10)] </pre> <p>The fact that you're creating a list of functions that are different due to capturing different values is worth emphasizing by making it a named function.</p> Thu, 08 Feb 2024 00:33:38 +0000 Loop variables shared between iterations - not just in Go https://lwn.net/Articles/961247/ https://lwn.net/Articles/961247/ milesrout <div class="FormattedComment"> <span class="QuotedText">&gt;a fix for a longstanding "gotcha" with accidentally sharing loop variables between iterations</span><br> <p> This is a classic issue. When I was just a beginner, I stumbled into the same problem in Python. A callback being constructed in a loop (maybe a list comprehension?) using 'lambda', which captures the loop iterator. The solution is clever: instead of [(lambda: i) for i in range(10)], you can do [(lambda i=i: i) for i in range(10)]. The default argument is evaluated when the lambda expression is evaluated. It looks odd, but it works.<br> <p> <span class="QuotedText">&gt;&gt;&gt; l1 = [(lambda: i) for i in range(10)]</span><br> <span class="QuotedText">&gt;&gt;&gt; l2 = [(lambda i=i: i) for i in range(10)]</span><br> <span class="QuotedText">&gt;&gt;&gt; [f() for f in l1]</span><br> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9]<br> <span class="QuotedText">&gt;&gt;&gt; [g() for g in l2]</span><br> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]<br> </div> Wed, 07 Feb 2024 22:21:22 +0000 Go 1.22 released https://lwn.net/Articles/961248/ https://lwn.net/Articles/961248/ Cyberax <div class="FormattedComment"> <span class="QuotedText">&gt; they've promised not to do</span><br> <p> Nope. No such promises were made.<br> <p> And error handling in Go is just fugly.<br> </div> Wed, 07 Feb 2024 22:13:40 +0000 Go 1.22 released https://lwn.net/Articles/961246/ https://lwn.net/Articles/961246/ milesrout <div class="FormattedComment"> It's never going to change. And that's a good thing. Not only is there no better way of doing it, but it would do something that, as far as I know, they've promised not to do: render most Go code that exists unidiomatic.<br> </div> Wed, 07 Feb 2024 22:11:36 +0000 Newsletter https://lwn.net/Articles/961223/ https://lwn.net/Articles/961223/ corbet It looks like they have a nice RSS feed ... yes, we'll add it, thanks. Wed, 07 Feb 2024 19:52:55 +0000 Go 1.22 released https://lwn.net/Articles/961222/ https://lwn.net/Articles/961222/ rbranco <div class="FormattedComment"> Please include the Golang Weekly Newsletter in the LWN Weekly Edition like you do with other languages. :)<br> <p> <a href="https://golangweekly.com/">https://golangweekly.com/</a><br> </div> Wed, 07 Feb 2024 19:51:36 +0000 Go 1.22 released https://lwn.net/Articles/961210/ https://lwn.net/Articles/961210/ Cyberax <div class="FormattedComment"> Super nice. For me, the only major pain point remaining is the error handling. <br> </div> Wed, 07 Feb 2024 17:31:58 +0000