One of my engineering highlights was Russ reviewing a few of my contributions to Golang (to the core http library). He's a super cool and nice guy. I don't really write that much Go anymore, but it was a fun & cute language when it first came out.
I once wrote him an email asking what font was used in the plan9 papers. He replied. It's Lucida Sans Unicode. He even provided a url to paper published by the maker of the font.
Zmij and xjb are in a league of their own. Broadly speaking, dtoa first has to find the shortest decimal representation of the floating-point input, and then format that decimal representation into a string. Zmij and xjb pull far ahead of the others mostly by speeding up the second part of that process.
uscale is quite good without the stringification, as are many other algorithms. I would say uscale's main strength isn't its speed, but rather its simplicity and, more importantly, the fact that it does both formatting and parsing using a single ~11 KiB table, which no other state-of-the-art algorithm offers (although yy comes close).
The core of newer methods like yy, xjb and zmij is remarkably simple: https://vitaut.net/posts/2026/yy-dtoa/. Shortest uscale is basically Schubfach or, rather, it's variant called Teju Jagua and has 2-3 wide multiplications compared to 1 for newer methods.
The complexity is optional and comes from squeezing the last few nanoseconds =).
Right, that's basically what I was trying to say (in so many words). I learned a lot from your dtoa blog posts and Zmij's implementation. Thank you!
> has 2-3 wide multiplications compared to 1 for newer methods.
As written, the `shortFloat()` function always calls `uscale()` two times, followed by an optional third call. Each `uscale()` does two wide multiplications (one full 64x64->128 and one 64x64->hi64, in case we want to make that distinction), so that works out to either 4 or 6 wide multiplications in total. I think `shortFloat()` could be rewritten to always do exactly 2 wide multiplications (both 64x64->128) at the cost of some more ALU operations. However, I don't see how that could be further reduced to only one wide multiplication.
EDIT: Going back to look at Zmij's to_decimal, I just realized that it also doesn't do just one wide multiplication in the sense I originally meant, so what you're saying is likely correct in the first place. I overzealously used a different definition of "wide multiplication", which I probably should've realized, given the fact that my numbers are exactly double yours, but alas. My apologies.
I love how proactive the crypto team is about post quantum. They released https://pkg.go.dev/crypto/mldsa. The lead maintainer Filippo Valsorda wrote a nice piece here[1] to urge the tech world to start deploying good enough versions of post quantum crypto.
While I'm highly sympathetic to competing priorities crowding out movement to pq cryptography. At the same time it's not sudden at all. It's been 10 years since nist first said "move shit over"?
"bold-faced lie" and "bald-faced lie" are both valid expressions. The original expression is "bare-faced lie" but they're all pretty similar to each other.
Yes but only one of them makes most people who hear it think you don’t know the expression you’re trying to use. There’s no objective reason it has to be this way, but it is, and at least personally I appreciate being told when I’ve got something stuck to my back.
I don't really know why I should care what expression I'm trying to use (or what someone else is trying to use) as long as the intent is understood. If anything, people who are needlessly pedantic about the way I express things that they clearly understood are people I'm happy to get signal from so that I can minimize my need to interact with them going forward; it's much nicer to find out from something inane like this than to wait until we have a communication problem about something actually important.
bold-faced lie is just the usual English drift that was actually questioned as incorrect when it first surfaced. If a lie is bold, you don't have to suggest that the user's face is bold when doing it. You can in thirty seconds of google searching find numerous sources explaining that "bold-faced" is a malapropism.
It's the usual English drift perhaps, but "bold faced lie" has been used since the 17th century, which is also apparent from "thirty seconds of Google searching". Three hundred years is enough usage for me to count it as correct.
On a side note, "bold faced" does not mean the persons face is bold, only that it is said boldly, which implies a level of rudeness that "bald-faced" or "bare-faced" does not.
Modern references seem to align (for instance, Garner's): Bald-faced and bare-faced have slightly different connotation than bold-faced. Despite "bold-faced lie" being in somewhat common use, "bald-faced lie" is more common (over 2x according to google stats), and overwhelmingly agreed upon as the "literate" choice, unless an author intends to refer to the sort of lie that would headline an article.
> Generally, something to be avoided by people striving for clearer communication
Their communication seemed pretty clear to me. If anyone actually claims that they didn't understand what they meant but would have understood it by using the other form of the expression, I think that's a bold-faced lie.
Chromium uses BoringSSL, which opens its readme as follows:
> BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.
> Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing so is likely to be frustrating because there are no guarantees of API or ABI stability.
This person was public on the recent nist list against hybrid solutions. I simply don't understand why they would oppose the safer option. Yes I've read the mailing list, it just all seems quite suspicious.
Unfortunately for people SELECTing UUIDs out of a DB directly into a uuid struct, the built-in uuid structs don't implement the necessary interface for that, so you'll have to continue using the google package, or a plain string.
The database/sql package gained native support[1] for the uuid.UUID type so it will Just Work even without the methods. This probably should have been mentioned in the release notes and database/sql package docs.
Repeating the package name is fine if it's exactly the same name (modulo capitalization) and there's nothing better to name the type anyway. The style issue would arise with e.g. uuid.UUIDVersion, which should just be named uuid.Version. There used to be a gopls lint that would flag names like uuid.UUID but it got relaxed awhile ago.
uuid.UUID is implemented as [16]byte, like most other UUID implementations out there.
If you want to keep your package implementation agnostic, use [16]byte as argument type; that's assignment-compatible with any other type that is such an array underneath:
> First, generic methods are now supported
> Generic functions can now be used without explicit type arguments
Great! This was an ergonomic code issue I hit when trying to create a universal handler/controller generic that could hydrate/populate function arguments (from a request body) without having an actual copy of the arguments: https://github.com/xeoncross/mid/blob/main/handler.go#L12
Thanks for the link, looks like a very pleasant framework to use! I was interested to see "Mid-fasthttp" on the slower end in the benchmarks at the bottom, do you know why that is?
Btw, the Gin and Echo examples reference an "input" variable but it doesn't seem to be defined there? Maybe it was intentional, since the examples are just to give a general idea of how the handler looks in each library, but thought I would let you know just in case it wasn't.
Due to the fact that fasthttp is not net/http compatible it is due to the conversion being required from a https://pkg.go.dev/net/http#Handler. It was included for information purposes as I though someone would be curious.
Go has had this behaviour for promoting fields (provided they don't clash) for some time, this is just extending the language feature to initialisers.
Your contrived example doesn't initialise the embedded struct that also contains a "Burrow" field. If it did that at all, even without naming the Burrow field... you would not be allowed to initialise the struct, because of the ambiguity.
The whole point is the implicit bug, when the field is added and initialisation code rewritten to take advantage of this feature, without the developer realising the clash in first place.
I'm not sure what I can say. One man's "source of bugs" is another man's "convenient syntax".
The rule errs in favour of the developer and the struct they can see. Initialising (or accessing!) a named field always picks the one in the top-level struct if you have one there. It'll be there because you added it. Promoted fields can only get promoted if they are unambiguous.
If you don't want to take advantage of that, you can write in full:
g := Gopher{
Name: "Gopher",
Burrow: "Burrow #42",
Habitat: Habitat{Burrow: "Wild Acres"},
}
fmt.Println("Your burrow: ", g.Burrow)
fmt.Println("I mean your _real_ burrow: ", g.Habitat.Burrow)
... but most Go programmers would look at the fact you named two fields the same and then nested them as an unforced error, a rookie mistake.
Most of them are very happy that they can embed some other type they don't know the full contents of, knowing they can access (and now initialise!) fields in it they care about, and thus don't give the fields in their own types the same name, while resting assured that if that other type later gains new fields they've never heard of, it's not going to clash with their own naming choices and break their code and force them to rename something. Their types' field names always come out on top, in their code.
You're doing "but what if I deliberately named my type's fields the same as the embedded type's fields?", which is like "but what if I deliberately stuck my hand in the meat grinder?" -- don't do that
The only, single, complaint is that this possible source of bugs should be part of go vet, just like in other programming languages static analysis tooling, Sonar, PVS, clang-tidy, Roslyn, Checkstyle, clippy, PMD,.... catch such kind of flaws.
However I see that I crash again in the Go versus other programming languages ecosystems mindset.
You, or $YOU, could add that as a linter and integrate it into golangci-lint [1]. There are many things in golangci-lint that I abhor and can't even imagine turning on, things that default to false that I can't imagine working without, and some things I think just bizarre... and everyone will have their own distinct list of such things. While one can argue about the virtues of things being in linters versus in the language I do think it's a useful way to resolve these sorts of issues without having to litigate the compiler itself. If I were ever to build my own language it would ship with an equivalent of golangci-lint and its open-source ethos of linting from day one.
In the before times this would be not very helpful but in 2026 this is probably about 30 minutes of your actual time and maybe a couple of hours of AI time. The code isn't too hard to write but there are a number of edge cases to cover, as there always is in this sort of thing.
Funny enough, in one of my projects I created a struct with a string field just to have a distinct type that couldn't accidentally be initialized by typing a string. This update completely messes that up lol
I've missed something - what were you expecting from that code? Would anyone expect the `Burrow` inside the `Habitat` to be initialised instead of the top-level `Burrow`?
I would say that initialising the wrong field because a dev is unaware of a clash between Gopher.Burrow and Gopher.Habitat.Burrow (naturally in more complex code), when upgrading to 1.27 and taking advantage of the feature without realising it, is a bug.
I love these release notes but I really wish they would add syntax highlighting to the Go blog. I'm always a little bit surprised/disappointed whenever I land on a go.dev link since I know the code will be just a little harder to visually parse than it needs to be.
There's a reason for this. Rob Pike was asked about it and said that syntax highlighting reminds him of the bright colors of children's toys and he personally disables it so that he can focus on the text.
I don't know why it's still like that but that's the original reasoning.
> Syntax highlighting is juvenile. When I was a child, I was taught
arithmetic using colored rods
(http://en.wikipedia.org/wiki/Cuisenaire_rods). I grew up and today I
use monochromatic numerals.
> Gofmt was written to reduce the number of pointless discussions about code formatting. It succeeded admirably. I'm sad to say it had no effect whatsoever on the number of pointless discussions about syntax highlighting, or as I prefer to call it, spitzensparken blinkelichtzen.
> When I was a child, I used to speak like a child, think like a child, reason like a child; when I became a man, I did away with childish things.
I sincerely hope Rob Pike was being sarcastic/ironic, because otherwise, he sounds insufferable
He sounds insufferable because he's calling syntax highlighting childish. Not simply politely saying it's not his thing. It's like he can't understand why anyone else would use it, or isn't bothering to. Maybe there's more nuance to what he said, but it's not obvious from the quote.
"Everyone who uses syntax highlighting is a child"
I mean, maybe he was genuinely trying to make a joke, but I'm well past the point of assuming random strangers are joking when they're being offensively dumb.
The reason traffic lights are colored is because they are showing distinct states of the same thing and the color is the means of differentiating.
Same for transit maps: different routes are colored to distinguish them from other routes, which is especially useful if they overlap.
But that’s not what syntax highlighting does.
The equivalent of your examples would be to not highlight the syntax at all, but only use color coding to distinguish variables.
The equivalent of how syntax highlighting currently works for your examples would be if the light fixture was one color, and the light pole was another, but then all the actual lights were the same color.
I actually think highlighting only the variables with distinct colors could be extremely valuable. Would certainly help avoid mistakes with nested i/j loop counters.
Edit to add: come to think of it, it would have been even more valuable in Go, until recently anyway. The variable color coding would expose the common loop variable instance bugs, because a programmer would be instantly puzzled by the unexpected coloring.
Your comment makes me think of LabVIEW - if you're not familiar with it, it uses a visual programming language ("G") in which data flows down wires. The color of the wire indicates the wire's data type (blue for ints, orange for floats, green for bools, pink for strings) and the width of the wire indicates the dimensionality of the data (thin line = scalar, thick line = 1D array, double-thick = 2D array). The color is more than decorative or even assistive - it's essential to understanding the program.
I still wonder why every open-source visual programming language is either a toy for teaching or straight up awful, often not implementing but even loops, when LabVIEW has been doing it right for decades.
Despite its huge size and it installing several services that constantly run in the background, it's still one of my favorite "languages" of all time. It's the only one I've ever seen people going from never having programmed before to making simple but meaningful contributions in within a single day.
That does exist, it's called semantic highlighting.
In any case, my analogy was not perfect, but neither was Russ's! The point is it's totally normal and not "childish" to use colours to help distinguish things. Traffic lights do not technically need colours (you can use the position of the lights - I assume that's what badly colourblind people do). Nor do transit maps technically need colours - you could just label the lines, or use patterns.
There are a bunch of identical things on my screen called lines. They contain a bunch of mostly identical things called tokens. Syntax highlighting uses different colors to identify the different purposes of all of these
tokens blasted onto my screen.
Unlike formatting preferences, the colours I use in my editor don't effect others. That said I might not mind living in a world where everyone used the same highlighting scheme, as long as it was reasonable ;)
That makes sense as a personal preference for him, but it's odd for that to still be the company/project stance. Like, surely he knows he's the minority for not wanting highlighting?
Apart from the fact that your comment is against the rules: please don't trivialize that quote. It has a profound meaning, and is completely out of place here.
There is a thread linked where we literally see gophers express the belief that they do not like syntax highlighting, and mock those who do - because Great Leader - born in 1956 - does not like syntax highlighting. Its called double think.
that's an extremely odd explanation and it makes me think that he has some hidden PTSD. it's also insane that one person's preference trumps the rest of the world's.
I understand and respect this position. I think syntax highlighting
is a highly subjective matter, bordering on personal preference with regard to shell interactions, editor configurations, bindings, shortcuts, snippets, and the like. It's also... insignificant somehow, like quibbles over formatting rules that Go settled once and for all with `go fmt`.
I often prefer not to enable syntax highlighting just for color. Occasionally I'd choose some minimal theme that only highlights string literals and keywords. So it has two or three colors. But some of the color schemes I see are a festival of lights where every special element of syntax has its own color.
I don't understand how that is supposed to help me parse anything and why the rules are complex. The `range` keyword needs to be purple, and `chan` must be navy blue. Why exactly? And every site has a different color scheme? There is no consensus, and there shouldn't be.
For a serious community-driven project like Go, dealing with the question of syntax highlighting is strange. The creators deliberately avoided the questions of IDEs and editors for Go, leaving them to the community. I think the same principle applies here.
> The creators deliberately avoided the questions of IDEs and editors for Go, leaving them to the community. I think the same principle applies here.
Exactly. This is fundamentally about accessibility (in the broadest sense). Do people have opinionated screenreader settings they like to force on others too?
I get the why, kind of - if you need colors to make sense of code, maybe the code isn't clear enough. If you send blobs of code through email and other systems that don't necessarily have syntax highlighting, it also makes sense. But on a website, whyever not?
Personally I can't say when I was last actually aware of syntax highlighting. The only time I'm actively engaged with it is to change the default low contrast comment color that a lot of themes have (for some reason, as if comments are unimportant / noise) to something better. For Go, I don't really notice when it has or doesn't have syntax highlighting, at least not on e.g. go's website.
When I started learning Go I went all in including using the recommended editor (acme editor) which has no syntax highlighting, no autocomplete and a very different way of writing code. My production went down a lot but the quality of the code went up a lot.
I think the lack of syntax highlighting was one reason for that. It makes you think more about the code you write and how it should compose, while a fully fledged IDE encourages you to just throw more code at the problem.
I think the ACME way should be used for love of code and ideally when you want to create libraries that stand the test of time.
When you just want to get things done fast bring the full IDE and now some LLM vibes and it’s done.
I go through intervals of turning autocomplete on and off. I think autocomplete is useful for boilerplate (similarly LLMs are useful for boilerplate), but I prefer not to use either when writing code where correctness is particularly important. This is because it’s easier for me to internalize what something is doing by typing it out. It’s actually more effort for me to understand code by reading it rather than writing it.
I experience something similar with system design, where the act of creating a diagram helps me to understand much faster than trying to read someone else’s diagram. It’s not because only I can create good diagrams (I cannot) but again because the act of creating one helps me internalize the design.
I think there's a lot of value to be gained from turning all modern day features off for once and just code "raw", no syntax highlighting, just typing out all the code. Doesn't even need to be your own code, manually transfering code over can also help a lot with your basic coding skills.
I think a lot of people lose this over time because it's easier to use templates, autocomplete and LLMs, work from a higher level. But it's nice to go back to basics. Consider also firing up Pico-8 and writing some really really bad code. It's got a very rudimentary editor, 40 columns of code, no syntax highlighting, and you're limited in how much total code you can write. It also helps with leetcode since a lot of leetcode uses game coding tricks like modulo operators, min/max/clamp, etc (that's as far as I got, don't judge).
The Go language is by itself more than enough to get a trademark. They only additional thing you can do with a font is get a design patent... for the font.
It's more likely that they don't feel the need to use the font they gave you (for your code editor) on code samples on their own web pages. As it's a custom font, the text would be susceptible to pop-in, or would visibly switch from one font to another, both of which are ugly.
So they have no specific font preference for code samples, they only show their Go-specific font on the blog post about it. They prefer fast loading and no jank over custom font.
EDIT: just force reload https://go.dev/blog/go-fonts and look at the first hyperlink, "golang.org/x/exp/shiny". Watch it visibly switch from generic monospace font to Go Mono as the page loads. Janky! They probably don't want that for all their code samples ever.
> Second, a key in a struct literal may now be any valid field selector for the struct type, allowing fields in nested or embedded structs to be initialized directly
It's been a while since I've written more than anything trivial in golang, but this seems like a big deal to me. As in, I can define a struct that is consistent and reusable in other structs
It will be very nice working with code generators like oapi-codegen that can generate either nested structs or very unwieldy struct names. So big in that context, but like you said just a nice qol improvement most of the time.
Agreed. I've recently translated a pangram generator project written in Rust [1] leveraging SIMD to do the same in Go [2] to see how it fairs in terms of speed - the results are pretty close. In my local machine I'm getting ~3GHz in Rust vs ~2.4GHz in Go, which I think is really impressive.
I still believe that SIMD support is one of the most underrated new features in Go.
It's relatively straightforward to read and to write code using Go's SIMD package (the caveat being that you have to convert your data to SoA manually), and it gives comparable performance to other languages, since there's little in the way of GC overhead, bounds checking, etc, in this case.
So SIMD not only increases performance on its own, but it also closes the performance gap between Go and C++ / Rust, which has been a major cause for rewrites in the past. The memory usage overhead due to GC doesn't go anywhere of course, so there are still performance reasons to "Rewrite in Rust", but it's now become much easier to just optimise the hell out of Go code instead.
Odin solves this by letting you declare all arrays as either normal (AoS) or SoA, which helps with this use case a lot. Otherwise very similar ideas, except all the memory goodies. Underrated language!
This was one of the times where it made some sense. A lot of their complaints were about GC, which Discord has had issues with in the past on other things. Notably, Discord switched from Cassandra to ScyllaDB for their messages, and cited the Java GC as a big reason.
You might want to follow this proposal, if you aren't already. It's the most recent one, and it's supported by quite a few “core members” of the Go Team. I don't think it'll land in 1.28, but I like the fact that it's still a feature that's being actively discussed.
Having worked a couple of greenfield go shops post generics, it’s still quite rare to find them in first party code. They’re just not that useful outside of library APIs. Proper algebraic data types would be a huge game changer.
Go is extremely easy to pickup. If you know any language you probably know Go already for the most part (channels notwithstanding).
I wouldn't say it is a "beautiful" language however. Though that is in the eye of the beholder, I don't think the Go designers were even really going for beauty.
They were going for readability. You can make some impossible to read code with C++ because the programmer was too clever, and the designers of golang wanted to avoid that.
They were, very unfortunately, outsmarted by said too-clever programmers. As such I would like to request my enums and ternaries be returned to me. Trust me, they will not make a dent in the messes people have still managed to create.
This is only a small piece of the story for what people say when they want tagged unions. Without all of the ancillary support in the language, like exhaustive pattern matching, it really doesn't count.
The C++ committee said the same thing, and gave us std::variant. They are painful to work with and do not really deliver most of the benefits people want.
That is a LOT of code (very ugly code, I would add) that could be replaced by `type Float = float32 | float64` in a language with actual support for union types.
Tagged unions are not union types. A union type is a supertype for any arbitrary collection of types, but a tagged union aka sum type is a single type with multiple data constructors, and does not require subtyping to be implemented.
I'm so glad the new uuid package landed - it's overdue but a very welcome addition! I've already replaced github.com/google/uuid with `uuid` in several projects
Used to code primarily in Java. Now my app stack is about 80% Go. I love that it enables lightweight application development. Glad to see the platform evolving with a focus on resource efficiency.
I’ve been able to run golangci-lint locally just fine.
However I’ve not had much success running it on CI, with at least the 1.27rcs. I encountered some panic deep within staticcheck, and ended up turning off that specific linter on CI (better than not running it at all).
There was a tracking issue for go1.27 support at [1].
However that is now closed, which might imply that it should be working.
Go was my first language, and I still use it every day for projects tiny (scripts) to massive (1M+ line microservice projects) and love it! Thank you to the Go team for everything you have done over the last 2 decades.
I like to imagine that one day we'll have a language that launched with all the features languages eventually add. The whole ecosystem of packages would be built on them instead of a legacy of more primitive language feature sets.
I mean one thing frontier models are really good at is porting code with pretty low level of supervision. Provided there are enough fans porting packages from other ecosystems should not be a big challenge.
Generic methods are a huge win for the language. I've been waiting on these kinds of improvements to the type system before resuming work on my database toolkit.
I know this is an extremely unwelcome comment but I just have to ask… have you considered rust? Especially for a DB.
I just had excellent success migrating a go code base to rust completely AI driven. It led to a healthy performance boost too, as now I don’t need to worry about GC pressure contortions.
Ecosystem is my primary concern when it comes to language choice and I'm not worried about speed differences between Go and Rust. Unfortunately, Python is probably still the most practical choice for backend/pipeline engineering at the moment. That does mean there are Rust libraries being used indirectly though.
> Generic methods are a huge win for the language. I've been waiting on these kinds of improvements to the type system ...
It's funny that you and many others have found the introduction of "generics" in Go to be highly valuable, considering one of the motivations for Go's existence was:
Its designers were primarily motivated by their shared dislike of C++[0]
One of the language features C++ provides, "templates", was explicitly rejected by the language authors as being antithetical to Go philosophy[1]. Thompson put it bluntly:
DDJ: In the presentation before the awarding of the Japan
Prize today, you were quoted on the distinction between
reasearch and development. [The former, Thompson stated,
was directionless, whereas development had a specific goal
in mind.] So in that context, is Go experimental?
KT: Yes. When the three of us [Thompson, Rob Pike, and
Robert Griesemer] got started, it was pure research. The
three of us got together and decided that we hated C++.
[laughter] [2]
I definitely recall the days when it was not uncommon to see members of the Go community speak out against the idea of generics and other type improvements for allegedly taking away from the language's simplicity. Thankfully that faction lost that argument or otherwise changed their minds, because I have seen first hand how issues with the type system can hold back larger scale libraries.
The position held for many years by the language authors was[0]:
Generics may well be added at some point. We don't feel an
urgency for them, although we understand some programmers
do.
Generics are convenient but they come at a cost in
complexity in the type system and run-time. We haven't yet
found a design that gives value proportionate to the
complexity, although we continue to think about it.
Meanwhile, Go's built-in maps and slices, plus the ability
to use the empty interface to construct containers (with
explicit unboxing) mean in many cases it is possible to
write code that does what generics would enable, if less
smoothly.
Once the community could no longer be held back, the golang FAQ presented a very different position[1]:
The Go 1.18 release added type parameters to the language.
This permits a form of polymorphic or generic programming.
The runtime also includes reflection, so preserving compatibility of the type system while adding generics was definitely a challenge, so adding generics to Go was definitely a great achievement.
Considering that Ian was already working on them before 1.0, and never stopped until a solution was found, we know for certain they were planned by at least one person on the Go team. If you are struggling to say that Go people are not a single monolith then sure. Nobody has ever thought people are a single monolith.
However, the original announcement makes the intent of the project clear: "Not yet", not "never". They were always planned to be accepted into Go. But not before an acceptable solution was found.
They have successfully been able to add major features such as generics without breaking 1.0 compatibility, and the trend is to continue than way. Well there is no major language feature in sight in fact.
Also major figures of the Go team (Russ, Ian, Rob, Ken) are gone.
I love Go because even minor versions deliver great value like this. The struct literal inits and generic methods are great conveniences to clean up clumsy boilerplate.
Not to mention it’s just a dream language to work with , especially when building concurrent applications. I love engaging all of my cores. And memory is so expensive nowadays
Minor versions are basically major versions for Go. They’ll “never” create a Go v2 because they prioritise maintaining backwards compatibility as a language feature, thus following semver rules, no majors.
Generic methods finally landing is huge. Having to write a separate typed method for every integer type was one of the most annoying boilerplate patterns in Go.
idk, hn is the only place I every see people actually not liking go and most times those are people who's job is just far away from fields go is being use in.
That comment is a good reminder that a good chunk of people commenting on HN are completely out of touch with the real world, the actual popular ecosystems out there, and what companies actually do and use nowadays to ship.
Being on the HN's homepage isn't as simple as "most upvoted articles in last X hours". They take into account upvote velocity: 40 upvotes in 40 minutes isn't the same as 40 upvotes in 4 yours.
Would you rather have yet another LLM-generated slop article in its place instead of an article covering a major release for a widely-used language? Out of all the articles that reach the HN front page, this is the one you have a problem with?
You can't terminate goroutines like individual threads, but there's no good reason to anyway. They designed the context system to be able to signal across goroutines and do cleanup that way
Non-cooperatively terminating a shared-memory thread is an inherently unsafe thing to do, and basically every runtime that has an API for it regards it as a design mistake. See, e.g., https://docs.oracle.com/javase/8/docs/technotes/guides/concu... and https://learn.microsoft.com/en-us/windows/win32/api/processt.... (POSIX's pthread_cancel is somewhat different, and avoids some of the worst failure modes, but at the cost of not actually consistently killing the thread when you call it—and it still has a lot of problems besides that.) So I don't think Go is ever going to add this, nor should it.
(Having the go statement return a handle that you can block on would of course be completely fine, but at this point they're probably not going to do that either.)
This was my original take when I learned the language, but I later realised “errors as values” is one of the strengths of the language.
I have run both Go and Python backends in production for years. There is an entire class of bugs present in Python services (missing error handling) that simply does not happen in my Go services.
Python puts the burden of knowing what exception types a function call will raise on the caller, in Go I just check for err. Even if I do not anticipate every failure mode the Go call will raise, I will always log the error and handle it in a controlled manner. I couldn’t count the number of times I’ve encountered an unhandled exception in my Python code, and often in such a case the logging will be lacklustre because you will just see a huge stack trace, but lose the contextual logging I would have automatically added in Go.
Perhaps a syntactic sugar is in order to reduce verbosity.
Some languages do it better, but it's really not a problem. It's just verbose, but people say that about Java and that never stopped it from being used everywhere
C++23 introduces std::expected, which is a simpler alternative to std::variant designed specifically for the result-or-error use case. You still don't get pattern matching, but Go-style tuples don't give you that either.
Pretty childish. People have no trouble looking past it when they care about actually shipping reliable software that properly handles all code paths. Including error paths that are ignored in so many codebases.
I don't think it's childish to dislike verbosity in a language. Readability is important. There is a reason why there are so many programming languages that compile to Go: https://github.com/ubavic/compiles-to-go
Wasn't Go supposed to be "simple"? I remember how Go advocates used to boast about not having generics and now it almost seems like Go is trying to become some sort of C# or Java Frankenstein. I'm not even trying to badmouth Golang - just legitimately confused.
> almost seems like Go is trying to become some sort of C# or Java Frankenstein
The original Go team was trying to avoid this:
"Java, JavaScript (ECMAScript), Typescript, C#, C++, Hack (PHP), and more [...] actively borrow features from one another. They are converging into a single huge language." [0]
That team has since moved on, and now Go has begun to join that convergence.
The problem is that most programmers seem to want to write Java, more-or-less. New, simpler languages come along, but once they get popular, the pressure is on to turn them into Java-likes. It happened to Python and now it’s happening to Go. It takes a strong will for language maintainers to say “no”, and their language will suffer in popularity as a result - see, for example, Ruby.
I would argue that languages like Java (C#, Kotlin, etc.) strike a very good compromise between modeling ability and comprehension, which is why they are popular and people gravitate toward them.
You can have more complex languages like Scala that provide stronger modeling ability, but at the cost of complexity. Golang started off as extremely naive/simplistic, and is now converging in some ways. But it still has a ways to go: no generics on interfaces, no unions/ADTs, no pattern matching, no proper enums, error handling leaves much to be desired, and much more.
As I've always said: every non-functional programming language, as it matures, it's adoption rises in enterprise, eventually starts to become more and more like Java in terms of it's syntax and feature-set.
https://research.swtch.com/fp
https://github.com/golang/go/blob/go1.27.0/src/internal/strc...
Zmij and xjb are in a league of their own. Broadly speaking, dtoa first has to find the shortest decimal representation of the floating-point input, and then format that decimal representation into a string. Zmij and xjb pull far ahead of the others mostly by speeding up the second part of that process.
uscale is quite good without the stringification, as are many other algorithms. I would say uscale's main strength isn't its speed, but rather its simplicity and, more importantly, the fact that it does both formatting and parsing using a single ~11 KiB table, which no other state-of-the-art algorithm offers (although yy comes close).
The complexity is optional and comes from squeezing the last few nanoseconds =).
> has 2-3 wide multiplications compared to 1 for newer methods.
As written, the `shortFloat()` function always calls `uscale()` two times, followed by an optional third call. Each `uscale()` does two wide multiplications (one full 64x64->128 and one 64x64->hi64, in case we want to make that distinction), so that works out to either 4 or 6 wide multiplications in total. I think `shortFloat()` could be rewritten to always do exactly 2 wide multiplications (both 64x64->128) at the cost of some more ALU operations. However, I don't see how that could be further reduced to only one wide multiplication.
EDIT: Going back to look at Zmij's to_decimal, I just realized that it also doesn't do just one wide multiplication in the sense I originally meant, so what you're saying is likely correct in the first place. I overzealously used a different definition of "wide multiplication", which I probably should've realized, given the fact that my numbers are exactly double yours, but alas. My apologies.
https://www.acm.org/articles/people-of-acm/2026/russ-cox
https://news.ycombinator.com/item?id=49327408
[1] https://words.filippo.io/crqc-timeline/
ssh (as noted in tfa) has had pq defaults since 2022.
On a side note, "bold faced" does not mean the persons face is bold, only that it is said boldly, which implies a level of rudeness that "bald-faced" or "bare-faced" does not.
You're probably referencing https://english.stackexchange.com/questions/137551/bald-face... — but see in particular the "Update" section of the top answer.
Modern references seem to align (for instance, Garner's): Bald-faced and bare-faced have slightly different connotation than bold-faced. Despite "bold-faced lie" being in somewhat common use, "bald-faced lie" is more common (over 2x according to google stats), and overwhelmingly agreed upon as the "literate" choice, unless an author intends to refer to the sort of lie that would headline an article.
Generally, something to be avoided by people striving for clearer communication. =3
Their communication seemed pretty clear to me. If anyone actually claims that they didn't understand what they meant but would have understood it by using the other form of the expression, I think that's a bold-faced lie.
see also https://www.reddit.com/r/BoneAppleTea/
It seems there's a big push happening behind the scenes.
> BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.
> Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing so is likely to be frustrating because there are no guarantees of API or ABI stability.
OpenSSL itself is a clusterfuck that doesn't really meet anyone's needs: https://cryptography.io/en/latest/statements/state-of-openss...
Kubernetes project will be the first one [3] I guarantee it.
[1] https://pkg.go.dev/github.com/google/uuid
[2] https://go.dev/pkg/uuid
[3] https://github.com/kubernetes/kubernetes/blob/2220c3853a2402...
[4] https://github.com/google/uuid/issues/221
[1] https://cs.opensource.google/go/go/+/refs/tags/go1.27.0:src/...
The rule has always been intended to cover types that have another word in them but still choose to pointlessly repeat the package name.
`uuid.UUIDGenerator` is a hypothetical example of the anti-pattern that would instead be better named as `uuid.Generator`.
Ocaml often just has it be T
so uuid.T
https://pkg.go.dev/github.com/domonda/go-types@v0.0.0-202607...
If you want to keep your package implementation agnostic, use [16]byte as argument type; that's assignment-compatible with any other type that is such an array underneath:
For an example, see the UUID logging of golog: https://pkg.go.dev/github.com/domonda/golog#Message.UUID
Great! This was an ergonomic code issue I hit when trying to create a universal handler/controller generic that could hydrate/populate function arguments (from a request body) without having an actual copy of the arguments: https://github.com/xeoncross/mid/blob/main/handler.go#L12
Btw, the Gin and Echo examples reference an "input" variable but it doesn't seem to be defined there? Maybe it was intentional, since the examples are just to give a general idea of how the handler looks in each library, but thought I would let you know just in case it wasn't.
type Habitat struct { Burrow string }
type Gopher struct { Name string Burrow string Habitat }
It will not initialise what one expects, here it is a contrived example, however it may not be easy to spot in more complex source code.
https://go.dev/play/p/dsY6tK5S8Ie
Better generics and improved SIMD are nice additions as well.
Your contrived example doesn't initialise the embedded struct that also contains a "Burrow" field. If it did that at all, even without naming the Burrow field... you would not be allowed to initialise the struct, because of the ambiguity.
https://go.dev/ref/spec#Composite_literals
> A key must not denote a promoted field inside an embedded struct if that struct is also specified by another key.
> Given the declarations
> .... field selectors may not denote overlapping fields:https://go.dev/play/p/CFWVXkFBOEX
Note that I added a name field to Line.
Oops now Object.name is empty, which is my point.The whole point is the implicit bug, when the field is added and initialisation code rewritten to take advantage of this feature, without the developer realising the clash in first place.
The rule errs in favour of the developer and the struct they can see. Initialising (or accessing!) a named field always picks the one in the top-level struct if you have one there. It'll be there because you added it. Promoted fields can only get promoted if they are unambiguous.
If you don't want to take advantage of that, you can write in full:
... but most Go programmers would look at the fact you named two fields the same and then nested them as an unforced error, a rookie mistake.Most of them are very happy that they can embed some other type they don't know the full contents of, knowing they can access (and now initialise!) fields in it they care about, and thus don't give the fields in their own types the same name, while resting assured that if that other type later gains new fields they've never heard of, it's not going to clash with their own naming choices and break their code and force them to rename something. Their types' field names always come out on top, in their code.
You're doing "but what if I deliberately named my type's fields the same as the embedded type's fields?", which is like "but what if I deliberately stuck my hand in the meat grinder?" -- don't do that
However I see that I crash again in the Go versus other programming languages ecosystems mindset.
In the before times this would be not very helpful but in 2026 this is probably about 30 minutes of your actual time and maybe a couple of hours of AI time. The code isn't too hard to write but there are a number of edge cases to cover, as there always is in this sort of thing.
[1]: https://golangci-lint.run/docs/plugins/module-plugins/
I understand the need not to break existing code that might have such fields.
I don't know why it's still like that but that's the original reasoning.
https://groups.google.com/g/golang-nuts/c/hJHCAaiL0so/m/kG3B...
> Gofmt was written to reduce the number of pointless discussions about code formatting. It succeeded admirably. I'm sad to say it had no effect whatsoever on the number of pointless discussions about syntax highlighting, or as I prefer to call it, spitzensparken blinkelichtzen.
> When I was a child, I used to speak like a child, think like a child, reason like a child; when I became a man, I did away with childish things.
I sincerely hope Rob Pike was being sarcastic/ironic, because otherwise, he sounds insufferable
https://www.biblegateway.com/passage/?search=1%20Corinthians...
Oh come on, I like syntax highlights, but this is not "insufferable". It's just opinions expressed strongly, with probably some tounge-in-cheek
"Everyone who uses syntax highlighting is a child"
I mean, maybe he was genuinely trying to make a joke, but I'm well past the point of assuming random strangers are joking when they're being offensively dumb.
The reason traffic lights are colored is because they are showing distinct states of the same thing and the color is the means of differentiating.
Same for transit maps: different routes are colored to distinguish them from other routes, which is especially useful if they overlap.
But that’s not what syntax highlighting does.
The equivalent of your examples would be to not highlight the syntax at all, but only use color coding to distinguish variables.
The equivalent of how syntax highlighting currently works for your examples would be if the light fixture was one color, and the light pole was another, but then all the actual lights were the same color.
I actually think highlighting only the variables with distinct colors could be extremely valuable. Would certainly help avoid mistakes with nested i/j loop counters.
Edit to add: come to think of it, it would have been even more valuable in Go, until recently anyway. The variable color coding would expose the common loop variable instance bugs, because a programmer would be instantly puzzled by the unexpected coloring.
I wonder if traffic lights were invented today, would it be just one light changing colour?
Despite its huge size and it installing several services that constantly run in the background, it's still one of my favorite "languages" of all time. It's the only one I've ever seen people going from never having programmed before to making simple but meaningful contributions in within a single day.
In any case, my analogy was not perfect, but neither was Russ's! The point is it's totally normal and not "childish" to use colours to help distinguish things. Traffic lights do not technically need colours (you can use the position of the lights - I assume that's what badly colourblind people do). Nor do transit maps technically need colours - you could just label the lines, or use patterns.
https://www.flickr.com/photos/gywst/1407078279
It's completely absurd to say that colours are childish because they can help children.
> Gofmt's style is no one's favorite, yet gofmt is everyone's favorite.
Opinionated standard formatting is now the default.
https://groups.google.com/g/golang-nuts/c/hJHCAaiL0so/m/6STj...
I often prefer not to enable syntax highlighting just for color. Occasionally I'd choose some minimal theme that only highlights string literals and keywords. So it has two or three colors. But some of the color schemes I see are a festival of lights where every special element of syntax has its own color. I don't understand how that is supposed to help me parse anything and why the rules are complex. The `range` keyword needs to be purple, and `chan` must be navy blue. Why exactly? And every site has a different color scheme? There is no consensus, and there shouldn't be.
For a serious community-driven project like Go, dealing with the question of syntax highlighting is strange. The creators deliberately avoided the questions of IDEs and editors for Go, leaving them to the community. I think the same principle applies here.
Exactly. This is fundamentally about accessibility (in the broadest sense). Do people have opinionated screenreader settings they like to force on others too?
Personally I can't say when I was last actually aware of syntax highlighting. The only time I'm actively engaged with it is to change the default low contrast comment color that a lot of themes have (for some reason, as if comments are unimportant / noise) to something better. For Go, I don't really notice when it has or doesn't have syntax highlighting, at least not on e.g. go's website.
I think the lack of syntax highlighting was one reason for that. It makes you think more about the code you write and how it should compose, while a fully fledged IDE encourages you to just throw more code at the problem.
I think the ACME way should be used for love of code and ideally when you want to create libraries that stand the test of time. When you just want to get things done fast bring the full IDE and now some LLM vibes and it’s done.
I experience something similar with system design, where the act of creating a diagram helps me to understand much faster than trying to read someone else’s diagram. It’s not because only I can create good diagrams (I cannot) but again because the act of creating one helps me internalize the design.
I think a lot of people lose this over time because it's easier to use templates, autocomplete and LLMs, work from a higher level. But it's nice to go back to basics. Consider also firing up Pico-8 and writing some really really bad code. It's got a very rudimentary editor, 40 columns of code, no syntax highlighting, and you're limited in how much total code you can write. It also helps with leetcode since a lot of leetcode uses game coding tricks like modulo operators, min/max/clamp, etc (that's as far as I got, don't judge).
https://go.dev/blog/go-fonts
I wonder if the Go fonts has been created just to get a trademark on the "Go" word...
It's more likely that they don't feel the need to use the font they gave you (for your code editor) on code samples on their own web pages. As it's a custom font, the text would be susceptible to pop-in, or would visibly switch from one font to another, both of which are ugly.
Their CSS says this:
So they have no specific font preference for code samples, they only show their Go-specific font on the blog post about it. They prefer fast loading and no jank over custom font.EDIT: just force reload https://go.dev/blog/go-fonts and look at the first hyperlink, "golang.org/x/exp/shiny". Watch it visibly switch from generic monospace font to Go Mono as the page loads. Janky! They probably don't want that for all their code samples ever.
It's been a while since I've written more than anything trivial in golang, but this seems like a big deal to me. As in, I can define a struct that is consistent and reusable in other structs
Sure a SIMD expert writing assembly can probably do a better job than an LLM using these new intrinsics, but it’s still massively faster.
[1]: https://github.com/tuzz/pangram-machine
[2]: https://github.com/nkanaev/pangram-machine-go
It's relatively straightforward to read and to write code using Go's SIMD package (the caveat being that you have to convert your data to SoA manually), and it gives comparable performance to other languages, since there's little in the way of GC overhead, bounds checking, etc, in this case.
So SIMD not only increases performance on its own, but it also closes the performance gap between Go and C++ / Rust, which has been a major cause for rewrites in the past. The memory usage overhead due to GC doesn't go anywhere of course, so there are still performance reasons to "Rewrite in Rust", but it's now become much easier to just optimise the hell out of Go code instead.
I do still wish it had discriminated unions (algebraic data types) and some better error handling ergonomics.
https://github.com/golang/go/issues/76920
You might want to follow this proposal, if you aren't already. It's the most recent one, and it's supported by quite a few “core members” of the Go Team. I don't think it'll land in 1.28, but I like the fact that it's still a feature that's being actively discussed.
I wouldn't say it is a "beautiful" language however. Though that is in the eye of the beholder, I don't think the Go designers were even really going for beauty.
https://github.com/splizard/tagged
However I’ve not had much success running it on CI, with at least the 1.27rcs. I encountered some panic deep within staticcheck, and ended up turning off that specific linter on CI (better than not running it at all).
There was a tracking issue for go1.27 support at [1]. However that is now closed, which might imply that it should be working.
[1] https://github.com/golangci/golangci-lint/issues/6643
I like to imagine that one day we'll have a language that launched with all the features languages eventually add. The whole ecosystem of packages would be built on them instead of a legacy of more primitive language feature sets.
Standard ML is a perfect programming language from the 90s. It unfortunately does not have a great eco system of packages.
https://xkcd.com/927/
I just had excellent success migrating a go code base to rust completely AI driven. It led to a healthy performance boost too, as now I don’t need to worry about GC pressure contortions.
It's funny that you and many others have found the introduction of "generics" in Go to be highly valuable, considering one of the motivations for Go's existence was:
One of the language features C++ provides, "templates", was explicitly rejected by the language authors as being antithetical to Go philosophy[1]. Thompson put it bluntly: And now, years later, generics are "a huge win."0 - https://en.wikipedia.org/wiki/Go_(programming_language)#Hist...
1 - https://commandcenter.blogspot.com/2012/06/less-is-exponenti...
2 - https://web.archive.org/web/20110521080746/http://drdobbs.co...
Rejecting templates does not mean rejecting generics.
This is provably incorrect.
The position held for many years by the language authors was[0]:
Once the community could no longer be held back, the golang FAQ presented a very different position[1]: 0 - https://web.archive.org/web/20170102202940/http://golang.org...1 - https://go.dev/doc/faq#generics
By run-time they mean compile-time? There shouldn't be a run-time penalty right?
Also, is there some measure of the additional compilation cost now that generics has been added?
However, the original announcement makes the intent of the project clear: "Not yet", not "never". They were always planned to be accepted into Go. But not before an acceptable solution was found.
They have successfully been able to add major features such as generics without breaking 1.0 compatibility, and the trend is to continue than way. Well there is no major language feature in sight in fact.
Also major figures of the Go team (Russ, Ian, Rob, Ken) are gone.
It sounds like the dumbest thing in the world, but I love the import system auto-adding stuff inside of vscode when I need it. just slick.
The `go fix` modernisers are also great, have already run them in several repos.
Not to mention it’s just a dream language to work with , especially when building concurrent applications. I love engaging all of my cores. And memory is so expensive nowadays
The tl;dr boils down to a combination of valuing both compilation speed and execution speed.
A goroutine that has to be killed (no other way to tell it to stop) is a bug.
(Having the go statement return a handle that you can block on would of course be completely fine, but at this point they're probably not going to do that either.)
I have run both Go and Python backends in production for years. There is an entire class of bugs present in Python services (missing error handling) that simply does not happen in my Go services.
Python puts the burden of knowing what exception types a function call will raise on the caller, in Go I just check for err. Even if I do not anticipate every failure mode the Go call will raise, I will always log the error and handle it in a controlled manner. I couldn’t count the number of times I’ve encountered an unhandled exception in my Python code, and often in such a case the logging will be lacklustre because you will just see a huge stack trace, but lose the contextual logging I would have automatically added in Go.
Perhaps a syntactic sugar is in order to reduce verbosity.
I try to avoid exceptions, is there any better ways? (Variant looks a bit more complicated but could be a totally OK alternative)
The original Go team was trying to avoid this:
"Java, JavaScript (ECMAScript), Typescript, C#, C++, Hack (PHP), and more [...] actively borrow features from one another. They are converging into a single huge language." [0]
That team has since moved on, and now Go has begun to join that convergence.
The problem is that most programmers seem to want to write Java, more-or-less. New, simpler languages come along, but once they get popular, the pressure is on to turn them into Java-likes. It happened to Python and now it’s happening to Go. It takes a strong will for language maintainers to say “no”, and their language will suffer in popularity as a result - see, for example, Ruby.
[0] https://go.dev/talks/2015/simplicity-is-complicated.slide#5
You can have more complex languages like Scala that provide stronger modeling ability, but at the cost of complexity. Golang started off as extremely naive/simplistic, and is now converging in some ways. But it still has a ways to go: no generics on interfaces, no unions/ADTs, no pattern matching, no proper enums, error handling leaves much to be desired, and much more.