Rendered at 10:44:58 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
beaker52 7 hours ago [-]
It doesn’t matter to me how good the LLM is at writing Go if the compiler can’t stop it from accidentally leaving another part of the software with invalid state as a result of a change the LLM is making.
What am I talking about? Nil and partially constructed structs are impossible to prevent the creation of in Go.
Sure, if you’ve got a small program with limited scope, that’s probably fine if you look through squinted eyes. But the teams I work with are working on sprawling, evolving software where the compiler saying “hey, that’s not a valid Widget” would be extremely useful and save much heartache.
An LLM does a good job of “checking” for other uses and “checking” if everything is going to work correctly, but - supposedly we’ve committed the concept to code so that the compiler can actually verify it - and Go intentionally permits invalid states of structs. This makes Go a fundamentally problematic language choice for the kind of software I work with teams on, LLM or not.
Cthulhu_ 57 minutes ago [-]
Fair criticism, it's my main gripe with Go as well - it's not strict enough when it comes to e.g. nil, enums, and type safety. Annotations are supported but they're just strings. Projects require additional tooling / linters to check for things like unchecked errors and many more "gotchas" that I think could (should?) be part of the compiler or standard tools. Trivial example, Go's compiler will error when you have an unused variable, but won't if you reuse and overwrite an error variable a dozen times and only handle it once.
But on the other hand, I suppose it makes it a bit more pragmatic - less checks makes for a faster compiler, and fast compilation was/is very high up in the language's requirements and motivation. If you want / need more strictness in your language, there's Rust, Java, C#, etc.
dnautics 19 minutes ago [-]
i never run into these issues in >100k loc of productionized llm generated elixir (nil safety, type issues). i wonder, is there something architecturally in go that makes this a particular problem?
larodi 30 minutes ago [-]
How about Swift and Erlang? Why are these always left out of comparisons?
jchook 5 hours ago [-]
Good point.
It's sometimes challenging to get a Rust program to compile... but if you do, it's probably going to work.
moomin 4 hours ago [-]
The authors make some good points: compile time and test speed matter, platforms matter. But they really dodge the whole “guardrails matter” thing. And guardrails are going to win long term.
As for readability, the fact that AI-written Go closely resembles human-written Go is not necessarily a point in Go’s favour.
toolslive 3 hours ago [-]
> "guardrails matter"
This thing has been solved in the 70s. Basically, have a powerful type system, and a compiler that beats you into submission when you try to stray from the straight and narrow. Languages like (S/OCa)ML, Haskell and Rust will bring this to you.
As a consequence, you fight the compiler, and once it submits, you have a good chance it's going to work. The compiler is also the ultimate refactoring tool here. Change the concept? Just change the type in the code and follow through by fixing the error messages the compiler spits out.
m00x 4 hours ago [-]
> As for readability, the fact that AI-written Go closely resembles human-written Go is not necessarily a point in Go’s favour.
There's just not many ways of writing Go. It's a very dull language. It was designed to be dull and easily understandable.
dnautics 17 minutes ago [-]
but there are a whole lot of ways you can mess up a dull language, like shitty variable names, bad code organization, etc.
if an llm has learned dumb things from dumb users it could disproportionately cause provlems versus other languages, just by being "in a sloppy mood" when writing go.
throwaway63467 1 hours ago [-]
Not panicking doesn’t mean working as intended, the biggest issue with LLM generated code is that it will do something that’s subtly wrong not that it will crash. It anything LLMs are too careful with Golang code and litter useless nil checks everywhere e.g. for function calls with pointer receivers. That whole fear of panics is totally overblown.
Pavilion2095 1 hours ago [-]
And by that point a program written in go has been deployed and making money for months. These are two wildly different languages, people should stop comparing them as if they're targetting the same niche. Checks and protections that rust has aren't necessary in most cases, but increase development and maintenance time.
soniczentropy 48 minutes ago [-]
Do you have some evidence of that? I use both daily and my experience has been the opposite, if anything. Once I was as proficient at Rust as I was at Go, the "increased development and maintenance time" disappeared completely.
apancyborg 53 minutes ago [-]
With test, which LLM are good at writing, you can reduce this tremendously. Even Rust won't protect you in this case, remember the cloudflare outage. At the end it is not the language, it is you intrinsic ability to architecture well your software from there any LLM can do the work.
baalimago 6 hours ago [-]
I've found that keeping very healthy test coverage solves issues like this. LLMs are very good at validating their own implementations with TDD.
dnautics 11 minutes ago [-]
i think they validate less with TDD; if you tell them a bare bones spec to validate they tend to write just that. if you write the test after, then their testing is causally conditioned on what was written. if you are going to write tests, it seems like teat first is way better than test last.
cookiengineer 6 hours ago [-]
With unit tests you gotta be careful though, oftentimes LLMs skip implementations with mockups that just say "not implemented yet" or similar and then the unit tests become pointless because they start to only test internal structures for being set / not default values.
For me it helped a lot to try to make containerized end-to-end tests and a custom TestMain for this, where I am using podman to run the integration tests. This way the end-to-end tests are forced to be on network level, and you can test protocol and API quirks much easier with LLMs.
Also, never forget to write a bootstrapping docs/ folder so that you don't have to re-explain these things all the time.
BodyCulture 2 hours ago [-]
Very good point, thanks for confirming that! What is the reasoning behind the Go design choices you described?
temphaaa 2 hours ago [-]
i am using nilaway from fb it's great for those
tgv 21 minutes ago [-]
It's from uber, I believe.
cookiengineer 6 hours ago [-]
So your problem is the default/zero values of properties?
In Go the convention is kind of to have a constructor pattern with a NewStruct(...) *Struct method that initializes all properties.
Also can't you build your own validator for that with the reflect package in the Add() method of your UI graph to prevent this sorta thing?
thayne 4 hours ago [-]
> the convention is kind of to have a constructor pattern with a NewStruct(...) *Struct method that initializes all properties
But that doesn't stop you from declaring a var s Struct, and never initializing it, or making a NewStruct {}.
> can't you build your own validator for that with the reflect package in the Add() method of your UI graph
Besides the fact that that would almost certainly significantly hurt performance, how would you be able to differentiate between unitialized data and data that was intentionally set to the zero value?
TheDong 6 hours ago [-]
The Go std library, as well as practically all go library code, is full of things that don't fully initialize all properties and things that nil-pointer-panic if you hold them wrong, so no, no matter what you do you have to deal with this wart of Go.
The go type-system is simply incapable of enforcing nil-safety without being no longer able to compile the go stdlib nor most code in the wild, so it's a quite valid criticism of the go type-system and language, and your comment doesn't hit on a valid solution.
0x696C6961 5 hours ago [-]
You're painting a picture where people writing Go are constantly drowning in nil pointer panics. This is not reality. You hit them occasionally and they're trivial to understand and fix.
thayne 5 hours ago [-]
nil pointer panics aren't nearly as bad as values getting zero initialized, then used in places that assume they were initialized, and getting subtle bugs because the state is inconsistent.
5 hours ago [-]
jeanbza 17 hours ago [-]
Definitely agree with this article.
At Netflix, I lead the Go language guild. We've been seen increasing reports of users finding their AI agents writing better Go code than other languages, and increasing reports of projects favouring Go over other languages.
- For a language team, Go is a dream. The `go fix` tooling, AST/SSA packages, ease of reading and writing `go.mod` (go mod edit, etc), and various other "platform"-y features make modifying Go code at scale way easier than other languages.
yosefk 17 hours ago [-]
Uber reported that their Go code has quantitatively more concurrency bugs than code in other languages, and while to me it seems obvious from looking at Go's concurrency model, this is backed by actual data. Is there any quantitative data to back the claim that Go is better in an LLM based workflow than another popular language?
rubiquity 16 hours ago [-]
Matches my experience as well. Go fans have conflated "can easily make something concurrent" with "does concurrency well." Go's primitives for concurrency should almost never be used directly and Engineers below a certain skill level shouldn't be allowed to use them directly ever for long running production code.
As another example, Go still has not yielded a correct implementation of Raft or Paxos while there are dozens in Java, C++, and Rust. Antithesis found some more bugs in HashiCorp's Raft implementation recently[0]. I'm sure etcd still has some kicking around.
Maybe this is a "don't throw the baby out with the bath water' problem but the general evolution of Go has been lackluster. I reach for Rust, Zig, and modern Java instead depending on the specific needs and constraints.
"This Raft library is stable and feature complete. As of 2016, it is the most widely used Raft library in production, serving tens of thousands clusters each day. It powers distributed systems such as etcd, Kubernetes, Docker Swarm, Cloud Foundry Diego, CockroachDB, TiDB, Project Calico, Flannel, Hyperledger and more."
etcd has had numerous liveness and safety bugs, with one happening as recently as December of 2025. Would you consider that a correct implementation?
You may be interested in knowing that the largest managed Kubernetes service in the world (AWS EKS) ripped out etcd for in favor of their homegrown consensus service for large scale EKS clusters: https://aws.amazon.com/blogs/containers/under-the-hood-amazo...
fl0ki 15 hours ago [-]
etcd is some of the most amateur code I've ever seen, despite being one of the oldest and presumably most mature "infrastructure" projects written in Go.
goBGP is arguably even worse.
I don't have a third place in mind that's even worth mentioning relative to these two.
alfons_foobar 12 hours ago [-]
just curious, what problems do you see with gobgp?
(I have only a rather basic familiarity with go, but was considering gobgp for an infra project...)
iscoelho 8 hours ago [-]
Not speaking to their code, but to start GoBGP has the worst performance of any BGP daemon by a large margin [1].
Garbage collected languages like Go will always have worse performance than lower level languages like C (frr and bird are implemented in C).
Gobgp is great if you want to embed it directly into a Go app though. Talos Linux has done that recently.
camkego 14 hours ago [-]
Sorry to pile on, but yeah, I wanted to use etcd during 2021 and 2022, around v3.5, but etcd had serious issues including silent data corruption. If you are curious, ask gemini flash "there were a number of etcd releases years ago where it seems a new wave of developers came in and started breaking everything"
Thaxll 14 hours ago [-]
I'd like to know what you base your statement on that the Raft implementations in etcd or CockroachDB are incorrect. Your original paper does not mention those implementations, so where does that claim come from?
gyesxnuibh 10 hours ago [-]
Having run a fleet of 100s of etcd clusters for 10000s of rps, and the fact that upstream runs tests similar to antithesis and recently partnered with antithesis [0], and jepsen has tested it long ago as well [1]. Etcd's raft algorithm is fine. Someone even did a TLA+ proof on it in the last couple years[2]. Yes there was a correctness issue a few years ago but otherwise the person you're replying to doesn't know what they're talking about. Also those bugs have nothing to do with the raft implementation, but instead the state machine implemented on top.
doesnt raft have a problem that it assumes no hysteresis? and that in general you can construct a latency graph that deterministically causes a permanent lock in the leadership election phase?
cobbzilla 9 hours ago [-]
Is the correctness of its implementation of the algorithm unaffected by bugs in this state machine? Maybe I missed something.
gyesxnuibh 7 hours ago [-]
The raft algorithm works and if you implemented a less complex state machine (like using a simpler kv store that doesn't need global event ordering via revisions and watches) it would work. That's what antithesis said they did to test the raft algorithms in the other article linked
iscoelho 8 hours ago [-]
"there was a correction issue" is downplaying it. Etcd is truly the worst example of Raft.
Etcd corruption and loss of quorum is extremely common in practice and the GitHub issues sit for years. The design is simple, the performance is modest, yet it still has still never been reliable, despite being marketed as so. I can't speak to whether this is specifically due to their Raft implementation, but I'd argue the entire codebase is over-engineered and questionable.
AlphaSite 7 hours ago [-]
My beef with etcd is that its neither performant nor reliable.
Its very much {reliable, performant, flexible} pick none.
gyesxnuibh 7 hours ago [-]
Their lock, leader election, sessions, and leases are all awful and I'd never recommend anyone to use those. But as a strongly consistent kv store and if you need the watch mechanics, its useful. It has its place and that's mostly being used by kubernetes.
ablob 10 hours ago [-]
Surely the King is doing it, so that must be the correct way. Look, the King even wears clothes and is totally not naked at all.
That the world runs on Kubernetes is no qualitative statement about the correctness of its Raft implementation. You can say that it's clearly good enough to not matter most of the time, but that is a different statement.
No matter who you look at, they're just cooking with gas like you do, and they can make mistakes in just the same way.
Now; I'm only attacking your argument. I do neither know nor particularly care about the correctness of that implementation itself. There's been better refutations of the claim you replied to in other answers anyway.
steve1977 6 hours ago [-]
It's not even a qualitative statement about Kubernetes.
otabdeveloper4 2 hours ago [-]
Kubernetes doesn't solve any technical problem, so the language it's written in is irrelevant.
Yasuraka 28 minutes ago [-]
I have a bunch of volumes that I'd like to get automatically attached and mounted to nodes on which their respective workload runs (which are automatically scheduled) who automatically fetch and mount their config files and secrets from a HA DB on demand. I also need some internal loadbalancing and integrations with something like certbot for all of my web workloads. Id also like to make sure that I get metrics and logs from every workload in some form.
Thats basically it for starters, what non-technical solution do you propose?
steve1977 14 minutes ago [-]
What I meant is that the fact that the world is running on Kubernetes is not a qualitative statement about Kubernetes.
literalAardvark 4 hours ago [-]
etcd is notoriously unreliable and one of the biggest problems in k8s.
I didn't know Go just isn't a good language for it, but now that I know I'm no longer surprised at etcd being problematic.
preisschild 2 hours ago [-]
Having maintained multiple etcd clusters for self-managed kubernetes the last few years I disagree with the "problematic" characterization.
Sure it may not be the best fit in a scenario where you want a cluster spanned over the entire globe (thats why GKE uses paxos-based Spanner instead of it) , but even spanned across an entire continent (in europe via glass fiber) it works quite well for me. Its one of the least problematic parts of the stack.
> As another example, Go still has not yielded a correct implementation of Raft or Paxos
> are you saying this implementation is wrong?
> That's not remotely what he's saying at all.
I'm v confused by this thread
quietbritishjim 15 hours ago [-]
I don't care for Go myself (especially its concurrency model, which is a total dinosaur in a world where we have structured concurrency) so I'm not saying this to support my favourite language, but:
That is literally what the comment says.
rubiquity 15 hours ago [-]
Thank you. I don't know why this is so complicated.
HAL3000 14 hours ago [-]
> Go is bad so "I reach for Rust, Zig..."
I hope my every competitor will take your advice to heart, as one of our competitors did when they read that "Go is not a memory safe language", so they wrote a blog about how they are porting to Rust. While our team was moving fast and using those "primitives that should almost never be used" around our long running production code base with success.
Some time has passed and now their company does not exist anymore and we have a lot of their clients.
Thank you!
sunrunner 10 hours ago [-]
Perhaps that company failed because it chose to port things to Rust and not because of Rust itself? Or any other number of reasons that survivorship bias might be mistaking.
4 hours ago [-]
xvedejas 9 hours ago [-]
Where would one ever read that Go is not memory safe? That's just a false claim, and anyone believing it would have probably gone out of business regardless of choice of programming language.
fulafel 4 hours ago [-]
Nobody serious claims Go is fully memory safe. Here's Russ Cox telling you concurrency is a hole in the memory safety: https://research.swtch.com/gorace
> Go's internal data structures like interface values, slice headers, hash tables, and string headers are not immune to data races, so type and memory safety can be violated in multithreaded programs that modify shared instances of those types without synchronization.[113][114]
gpm 7 hours ago [-]
By a strict definition of memory safety it isn't - you can tear two-pointer-wide values using data races and cause arbitrary memory issues if you try to using only normal code.
It's close enough for most purposes... but it isn't.
pstuart 8 hours ago [-]
My ex-boss was a JS guy and then moved over to Rust. He loathed Go because it has pointers and it's possible to use a nil pointer if you are not competent.
JS is fine for what and where it is, Rust is fine too. I just appreciate the stupid simple nature of Go and it does the job just fine.
za3faran 10 hours ago [-]
What domain is your company in?
jerf 14 hours ago [-]
You seem to be implying, based on the rest of the thread, that Go has some sort of special defect that keeps it from implementing Raft correctly. But the "special defect" that Go has is that it in practice implements the same primitives in practice that almost every other mainstream language does, rather than implementing some sort of super-safe concurrency primitive like Erlang or Pony, or being immutable like Haskell. And even those things are of only marginal utility for Raft, preventing some local issues, but the hard part of Raft is more in the logic and the communication, for which none of these languages have any sort of special support or anything that will particularly help you get it right. Of the languages you listed only Rust provides any assistence over the standard mainstream languages, and like I said, in the context of Raft, it is not necessarily all that helpful.
If you want to see something that could potentially impact Raft's correctness, search the last couple of days of the HN front page for choreographic languages [1]. But none of these are even remotely mainstream enough to depend on for anything. Nor do I know if anyone in these languages has implemented Raft. A rather good test case for them, if any of them are looking. That's something that could actually help a Raft implementation's correctness, not just fiddle around the edges of local concurrency issues.
Also, wasn’t this about concurrency? You could, if you really wanted, write a paxos or raft implementation with no concurrency.
ramoz 16 hours ago [-]
That does not seem like a fair/accurate reference?
The antithesis author states:
"we’ve found bugs in every Raft implementation we’ve tested, including HashiCorp Raft, Aeron Cluster, OpenRaft, and MicroRaft"
rubiquity 16 hours ago [-]
You're misreading what I said. I didn't say other languages don't have buggy Raft/Paxos implementations, just that Go is yet to yield a single correct one.
jibal 16 hours ago [-]
I think you're projecting. You wrote
> Go still has not yielded a correct implementation of Raft or Paxos while there are dozens in Java, C++, and Rust.
That says that there are correct (i.e., bug-free) implementations in those languages. The GP noted
> "we’ve found bugs in every Raft implementation we’ve tested, ..."
which says that there aren't any correct ones. You then wrote
> I didn't say other languages don't have buggy Raft/Paxos implementations
which is a strawman. The issue is whether there are correct implementations. That there are buggy ones is irrelevant.
(FWIW I have no dog in this fight ... I'm just reading here.)
Someone 4 hours ago [-]
> The GP noted
>> "we’ve found bugs in every Raft implementation we’ve tested, ..."
> which says that there aren't any correct ones
That only follows if the GP tested every Raft implementation in existence and no new ones were written since.
rubiquity 15 hours ago [-]
The intersection of the set of Raft libraries Antithesis tested and all Raft libraries in existence do not fully overlap. I personally have worked on multiple proprietary ones that Antithesis would not have access to.
_dain_ 12 hours ago [-]
I work at Antithesis, we're happy to test out any Raft implementation that has so far escaped our notice :)
rubiquity 10 hours ago [-]
I love what you all do! I don’t have any to submit. Enough time with consensus teaches you to avoid it unless it’s really, truly needed.
0x696C6961 10 hours ago [-]
Lol "I swear have a girlfriend, she just goes to a different school"
jibal 15 hours ago [-]
Even if so, the "You're misreading what I said" charge was bogus and it would be nice if you admitted that.
Edit:
> What are they implying by citing that? That Raft implementations in all languages have bugs?
That's what it says.
> I've already pointed out that is false.
You claimed that, and it's being disputed.
> Please let me know, since you're so comfortable speaking for them.
This has veered into bad faith ... I won't comment further.
overfeed 15 hours ago [-]
Further, they can still edit their comment to correct it, but opting not to.
rubiquity 15 hours ago [-]
But they are misreading what I said. My original post is clearly about Go. What they wrote is also ambiguous.
> The antithesis author states:
> "we’ve found bugs in every Raft implementation we’ve tested, including HashiCorp Raft, Aeron Cluster, OpenRaft, and MicroRaft"
What are they implying by citing that? That every language has a Raft implementation with bugs? Yes that's probably accurate because lots of people make Raft implementations for fun and learning. Again, Go does not have a single Raft/Paxos implementation that is rock solid. I have seen many in C++, Java, and Rust that are doing tens of millions of requests per second in production for over a decade.
Is their point that Go is not the only language with this problem? My post already points out the track record is that Go is the problem for writing correct code in highly critical domains.
Dylan16807 14 hours ago [-]
If we rely on their evidence alone, it suggests nobody has ever made a correct implementation, so we learn nothing about Go. "Go has yet to yield a correct one" is an extremely misleading way to present evidence that says the same thing about every language.
The only way this becomes useful for comparing languages is if somebody gives evidence of correct implementations in other languages. You're claiming they exist but with no evidence and suggesting they're secret. How do you know those don't have bugs? Did any concurrency bug experts do extensive testing on them? And can we disprove secret Go implementations of the same quality?
FireBeyond 7 hours ago [-]
You're being very mealy-mouthed, even here, it reads as "The pre-eminent Go implementation can't even get it right" and yet the implementations Antithesis tested in Rust are apparently people's random "fun and learning" projects, nothing serious, and certainly not all the proprietary implementations that you've used that are all correct.
jibal 7 hours ago [-]
Also, it simply isn't true that @ramoz misread what they wrote, as I pointed out in both of my comments.
joshuamorton 14 hours ago [-]
> That every language has a Raft implementation with bugs? Yes that's probably accurate because lots of people make Raft implementations for fun and learning. Again, Go does not have a single Raft/Paxos implementation that is rock solid. I have seen many in C++, Java, and Rust that are doing tens of millions of requests per second in production for over a decade.
No, they are citing that every Raft implementation that Antithesis has tested has bugs. The etcd implementation you note in go that has bugs also does tens of millions of QPS and is over a decade old. How are you confident that the proprietary implementations that presumably haven't been fully tested don't have subtle bugs that don't show up in practice?
mrsilencedogood 15 hours ago [-]
To combine both TFA with this comment: I find that LLMs are ~fine at generating/editing gocode, or at least as ~fine as they generate most mainstream languages.
But good god, the second it gets to anything concurrency-related, it just loses its mind. As much as it's gotten vaguely ok to try to let the agents loose on some bits of the codebase, they simply can't even do table stakes stuff with the kinds of concurrency you see in real life.
nasretdinov 14 hours ago [-]
Correct concurrent code is mind-bogglingly hard even for seasoned veteran humans (and don't get me started on distributed programming...), so it's hardly surprising that LLMs with their limited context windows into the code have a hard time writing correct concurrent code
rubiquity 15 hours ago [-]
My experience as well. LLMs also struggle with Rust's many abstractions and offerings but you can know that if it compiles it is data race free and work with the LLM to use better abstractions over time.
Zig is also good at this but requires more up front design (thread-per-core, static allocation, etc.) and consistent checks to verify rules are followed.
bb88 13 hours ago [-]
C/C++ has "compiles but may have undefined behavior". Golang has numerous "compiles but has incorrect behavior" (normally known as footguns). Meanwhile with Rust, if you get past the compilation step, bugs become much much fewer. (You can still have memory leaks, but those are easily traceable).
It seems like claude code can code Rust pretty well with Opus, and I've started moving codebases away from Golang to Rust at work with Opus. Spin up an LLM and it cranks on it for a while, and as a benefit, I get easy apis to build on with other languages.
And that's the problem with Golang really, not that it's a bad language per se (all languages have footguns), but that the language interoperability story is terrible. Meanwhile Rust and Python/C/C++ go great together like peanut butter and chocolate. And I love it.
maleldil 8 hours ago [-]
> You can still have memory leaks
And deadlocks. "Fearless concurrency" helps a lot, but logic bugs are still possible.
za3faran 10 hours ago [-]
I wouldn't be surprised if Java has a much better experience here. After all, java.util.concurrent has many great implementations, and Java's `record`s are immutable, as are it's upcoming value types.
Pxtl 10 hours ago [-]
I was thinking same but C#.
hintymad 16 hours ago [-]
Java has so many excellent concurrency containers, plus robust 3rd-party containers like JCTools. It puzzles me why Go communities do not offer such containers.
Groxx 9 hours ago [-]
No thread/goroutine handles for fork/join handling from "outside", and no generics for many formative years that influenced tons of habits, then significantly weaker generics (improving very soon[1]), have all led to most concurrent code to be very "intrusive" - you create bare threads and add bare synchronization primitives (or nearly) by hand inside the threaded code to make it concurrent. `errgroup` is as far as a lot of code goes, in terms of sophistication.
Java leans heavily in the other direction: a lot of concurrency is added externally, without changing existing code, often in very declarative-flavored ways.
E.g. Future<T> serves as a foundation for a ridiculous amount of stuff, while Go forces channels for `select` whether they model your problem nicely or not, and they're very difficult (often impossible) to wrap without changing semantics.
There are very obviously lots of counter-examples for both langs (`synchronized`, rill in Go, etc), and I expect Go to become more Java-flavored in time (it already has moved this direction somewhat, and 1.27 will enable a lot more). But I think it's a fair summary of broad ecosystem habits.
> Go still has not yielded a correct implementation of Raft or Paxos while there are dozens in Java, C++, and Rust. Antithesis found some more bugs in HashiCorp's Raft implementation recently[0].
the source you link to contradicts your own claims.
they say:
> we’ve found bugs in every Raft implementation we’ve tested, including HashiCorp Raft, Aeron Cluster, OpenRaft, and MicroRaft
(besides Go, that's 2 in Java and 1 in Rust)
tptacek 7 hours ago [-]
The Raft bugs are the wrong kind of concurrency --- they're distsys bugs, not multithreading bugs. Not a good example, and a little telling that you'd cite it.
a2ff6eeb0 11 hours ago [-]
Yeah, but AI is better at debugging than people are, so what's the issue?
jeffbee 15 hours ago [-]
What primitives are we discussing? Any Go programmer can and should use the `go` keyword and the `sync.Mutex` type from their first program.
closeparen 14 hours ago [-]
It's pretty easy to get yourself into trouble with channels: deadlocks, send on closed, channel leaks, deadlocks "fixed" thoughtlessly with arbitrarily-sized buffers, etc.
jeffbee 14 hours ago [-]
This seems to have little to do with Go's facilities. Any concurrent program has hazards like these.
closeparen 13 hours ago [-]
In my experience, shared memory instills the appropriate fear and caution, while the apparent simplicity of channels encourages novice Go programers to take on concurrency projects beyond their abilities and without due care. Been on both the submitter and reviewer side of that plenty of times in 10 years.
treyd 7 hours ago [-]
Rust's concurrency libraries leverage the type system to make these issues much harder to encounter.
vips7L 17 hours ago [-]
You know there’s no quantitative data. It’s vibes from the top down.
andai 15 hours ago [-]
Which languages are they comparing with? From what I understood, Rust makes stronger correctness guarantees, including with regard to concurrency, but has a much higher learning curve and cognitive load.
Just reading the abstract, it talks about finding a number of bugs (across millions of lines of code) but I didn't see any claims that there would be fewer bugs in a different language.
Go obviously does not stop you from writing buggy code. Neither does rust or zig or whatever. Does go make it more likely to have bugs? Or a specific class of bug? Like, the real world is about trade offs.
mac-mc 10 hours ago [-]
Uber has fairly large golang and java codebases so they have more of an apple to apples comparison here since they are both GC languages of a similar performance class. And if a large population tends to make more mistakes with 200hp sedan A vs 200hp sedan B, there is probably something up with the design of sedan A.
wredcoll 9 hours ago [-]
I agree, but does that study claim there are more errors per line/function/whatever in golang than java?
pstuart 7 hours ago [-]
That article is meh. All of those issues are either addressed or junior programmer mistakes.
Yes, it's a bit of blame the user which will likely get the retort of "but I thought Go was perfect for junior engineers?"
Yes, there are footguns but none of the points therein were compelling.
orphereus 16 hours ago [-]
Trust me bro
paulsutter 10 hours ago [-]
The best way to write concurrency in any language is a single threaded polling loop. Goroutines and messages are just as bad as all the other alternatives, which is to say they are a miserable way to write code.
But Go is also perfectly good at single threaded polling loops.
cyanmoonx 15 hours ago [-]
Uber has a history of blaming the tool - in Facebook fashion - rather than admitting their “talent” sucks and they didn’t hire on merit.
They used to blame Python a lot too - Python is slow compared to others but not so slow to matter that much, and you can build other services around it to handle certain work.
Facebook - who chose PHP - used to blame iOS/Obj-c as the reason they couldn’t build a decent Facebook native app in the early days (anyone remember Fastbook?)
I would take it with a grain of salt.
gnull 15 hours ago [-]
What concrete arguments are there to believe in your talent hypothesis instead of their tool hypothesis?
A couple more comments like this from you, and I'll be able to say, "cyanmoonx has a history of blaming the talent rather than bad tools". There being a history like that is neither an argument for nor against tools being bad. And also, don't forget that bad tools and bad talent don't rule each other out.
purplemoonx 14 hours ago [-]
[dead]
driftproofhq 16 hours ago [-]
[flagged]
colwont 14 hours ago [-]
yup, show receipts
gertlabs 7 hours ago [-]
We've seen a pretty consistent pattern in our evaluations where Go is among the languages that models perform worst with (alongside Python), for reasons unclear. Our coding evaluations are typically measuring the foresight and planning expressed in code that is run in interactive environments/games.
This trend has been there since we started evaluating models using different languages in February 2026 and if anything, the disparity has grown in frontier models. Even Google models prefer Kotlin/C#/Rust for coming up with creative ideas (compilation success is a different story). Data at https://gertlabs.com/rankings
That being said, models love to recommend Go, and Go does have a lot going for it, especially if you are serving a public-facing website. So most of our public facing API handlers are written in Go, and we offload some of our most important binaries to Rust. There are just too many reasons not to use the languages that models think a little more effectively in.
zero_shift 16 hours ago [-]
I work at a large devsec company which uses primarily Go and TypeScript
I've found that the LLM generated Go has few mistakes, and generally isn't too obscure. But the volume of code is so high, colleagues do a bad job of reviewing it.
I've seen a lot of very silly decisions made, like returning the wrong HTTP code, or miscategorizing a metric used for an SLO, that I just don't think is helped by the sheer volume of code one has to wade through.
Ironically, we are considering migrating some initiatives to Rust, exactly because experiments indicate it works well with LLM development.
jeffbee 15 hours ago [-]
Isn't any equivalent system going to have more statements in Rust than it would have in Go?
bb88 13 hours ago [-]
Yes, and that's the case I've seen as well. I would also say rust is also more heavy on symbols, which can make code look kinda hard to parse in places.
But weirdly Opus (N=1) in Claude Code does okay on it. Enough I can reliably have it write software and feel confident it works.
super_flanker 14 hours ago [-]
Why would you think so? Rust provide better type system and abstraction mechanisms compared to Go, hence equivalent system should have less lines of code, at least in from my experience.
icedchai 14 hours ago [-]
Considering every other line of Go is `if err != nil`, this makes sense. I do prefer Go's simplicity, personally.
jdc0589 17 hours ago [-]
> For a language team, Go is a dream.
I agree very strongly. There's no debate about things that have 1000000 permutations in other languages. e.g. The correct format can always be checked by `go fmt` with no real config options. the end.
zero_shift 16 hours ago [-]
I mean this isn't true, formatting is the most trivial part. And so many languages have an opinionated formatter these days (e.g. Black)
overfeed 15 hours ago [-]
>> ...there is no debate...
> ...And so many languages have an opinionated formatter these days
The crux of gp's post is for Go, there is no debate as 'go fmt' is the only one that matters. Black is great, but some people prefer Ruff, leading to ...debates about which formatter the team/org should use. Go's batteries-included philosophy makes those discussions moot on so many levels beyond formatting.
ciupicri 13 hours ago [-]
As if projects haven't used to have a coding style. What's so hard in saying that code should be formatted with Black, yapf, ruff etc, beats me.
badrequest 8 hours ago [-]
Literally within this thread someone has already suggested using ruff instead of Black and nobody here are colleagues.
the_sleaze_ 7 hours ago [-]
It's a silly argument and the lowest form of bike-shedding on the level of tabs vs commas. People with no other substantive contributions use formatting as a beard.
The first one to choose it (whatever it happens to be) wins and that's the end of it. If it isn't the end of it you've got a talent issue.
overfeed 6 hours ago [-]
> It's a silly argument and the lowest form of bike-shedding on the level of tabs vs commas
Guess what other low-level bike-shedding argument 'go fmt' obviates? That's right - tabs vs spaces!
> If it isn't the end of it you've got a talent issue.
I know you meant this as a slur, but the implication is Go works better than other languages for those who have what you call "a talent issue"
maleldil 8 hours ago [-]
Bad example. Ruff's formatter has the same style as Black. It's documented as a "drop-in replacement". The difference is mostly performance.
In any case, that's a single decision the project lead takes once.
pmarreck 16 hours ago [-]
what is "Black"? (For hopefully obvious reasons, I couldn't find results with google, lol)
Dylan16807 14 hours ago [-]
What did you search?
If I do the simplest possible thing that isn't a single word, by highlighting "opinionated formatter these days (e.g. Black)" and clicking search, I get the right result. I also get the right result for black formatter, and I get the right result if I yolo the entire comment as my search.
Similar to black but faster, written in Rust, by the same team who created uv.
marcus_holmes 14 hours ago [-]
So... A: not trivial. And B: not part of the language.
> mean this isn't true, formatting is the most trivial part. And so many languages have an opinionated formatter these days (e.g. Black)
I don't think this is correct
frollogaston 11 hours ago [-]
This back-and-forth is a good example of why Go benefits from having a centralized linter. And uv isn't the official Python package manager even though it should be.
maleldil 8 hours ago [-]
I don't get why this is a big issue. This isn't some recurrent decision to be made. It's something a lead decides once and the project follows. That's it. Many companies have style guides anyway (eg Google[1]); the choice of a formatter is much simpler.
Because at some point you have to interact with some other team or project that made a different decision. And whatever you picked might fall out of favor and lose support. There's already a graveyard of Python type linters, including Google's pytype.
Especially the uv thing. You clone some non-uv git repo that has no pyproject.toml and you don't know what to install. Maybe has requirements.txt but it's partially wrong.
TimByte 3 hours ago [-]
[dead]
giancarlostoro 16 hours ago [-]
Your post reminds me of what I love about Python, we have PEP-8 which is a style guide, and it kind of shifts how you write code a bit (for the better) which is something I sorely miss in other languages, I don't get the feeling people care about style guides for other languages very much.
osigurdson 9 hours ago [-]
If you know any other language, you basically already know Go (with the exception of the channels stuff). The biggest pain is the if err != nil stuff, which I know some people like but it is suboptimal in my view. While far better than C# and Java's exceptions, far worse than Zig's model.
throwaway2037 7 hours ago [-]
> far better than C# and Java's exceptions
What is wrong with them? When writing enterprise CRUD apps, they are very useful.
pjmlp 2 hours ago [-]
Yeah, panic/defer/recover are so much better. /s
kromem 5 hours ago [-]
Yep. Have a primarily Go backend and from even early on the agents were doing a good job.
Now they are even better than me.
I do think the way software is organized for primarily agent driven repos will need to change a bit from how I preferred setting things up. (Guessing we're going to be returning to a world of microservices in the near future.)
dzonga 15 hours ago [-]
Go wins for simplicity. however what I have seen is companies end up going with Java coz it's simple enough - not simple as Go, but simple enough + fast enough.
though the letdown with Java is the wider ecosystem that makes unwarranted contraptions out of simple things.
frollogaston 10 hours ago [-]
Go's big advantage was M:N threads. Java's biggest flaw has been the lack of cooperative multitasking, which people worked around by mangling their code with promises. Now Java has M:N threads too thanks to Project Loom, but there's so much code written before that will never really go away.
pjmlp 2 hours ago [-]
Java already had M:N threads in the early days, aka green threads, because the JVM and Java specifications did not assert what kind of threading was to be provided.
Thus most JVM implementations had a mix of red (1:1:) and green (M:N) threads, eventually only red threads were kept in the surviving implementations.
With Project Loom now both models are officially supported and part of the specification.
frollogaston 2 hours ago [-]
Yeah I've heard of the Java 1-2 greenthreads, but supposedly those were M:1, ie you could only run them on one core. At least this SCO release note linked from Wikipedia says that: https://www.sco.com/developers/java/j2sdk122-001/ReleaseNote... And the pros are more about compatibility than performance
pjmlp 48 minutes ago [-]
How have you found a SCO note, which never did nothing relevant for Java?
Here from Oracle, as historically taken from Sun documentation for JDK 1.1.
=> Many-to-Many Model (Java on Solaris--Native Threads)
I think there's a naming confusion here. You said "M:N threads, aka green threads". However, your linked document clarifies that "green threads" are the M:1 threads that "[do] not exploit multiprocessors" (see the "Green Threads" parenthetical in the first subheading). It is interesting that JDK 1.1 also had an M:N threading model, but that's not what people usually mean by green threads.
bushbaba 10 hours ago [-]
Go is heavily opinionated on style, design, and semantics. Its design was around being as concise as possible…which means token efficient.
Yeah Go is my preferred language to code with AI. Second up is type script. Followed by Java, then Python.
joaohaas 10 hours ago [-]
Go design is not around being concise as possible, in fact it's the complete opposite.
One of the cores behind Go is to make language simple, even if at the expense of more verbose code.
Two main examples of this is the infamous 'if err != nil' and how you handle filter/map/funcional operations.
bushbaba 9 hours ago [-]
Yes but it’s err not error. The variable and method names are meant to be concise and highly readable without the CS fluff of Java naming hell.
joaohaas 9 hours ago [-]
I don't think naming convention is the kind of stuff that helps save tokens, specially considering how text is tokenized.
On the other hand, being able to write 'list.filter(v => v.selected)' (or something similar) instead of:
listFiltered := []Item{}
for _, item := range list {
if item.selected {
listFiltered = append(listFiltered, item)
}
}
would save much more tokens.
maleldil 8 hours ago [-]
You can have that with generic functions, although Go's lambda syntax is too verbose. The slices package has DeleteFunc, which is kind of the opposite. I don't know why they have Filter.
They use more than just Java. The UI was originally C#... I'm still surprised the front-end was C# but they went with Java longer term for the backend.
dotwaffle 16 hours ago [-]
When I worked at OpenConnect (Netflix's CDN) there was a lot of Python too, and I started porting a lot of the tooling to Go. By the time I left (2019), Go was really starting to take off outside of OpenConnect too -- but yes, there's historically a huge amount of Java there.
seabrookmx 15 hours ago [-]
Likely because Netflix relied on Silverlight for video playback early on. I'd be surprised if they still had C# in their front-end stack (and I say that as a general C# fan, though I use it on the back-end).
giancarlostoro 14 hours ago [-]
My favorite thing about it having Silverlight is Silverlight actually worked on Linux better than Flash did. I think I used the Mono version of it though, I don't remember?
0x457 15 hours ago [-]
Their UI originally was Silverlight which at that time had the best "adaptive streaming" story.
allset_ 15 hours ago [-]
Large companies use more than one language.
14 hours ago [-]
14 hours ago [-]
fishfasell 11 hours ago [-]
I assume it's because Go is so opinionated? I experimented with it and found it almost boring to write, but I strangely loved it. Now in the AI era I crave the forced uniformity.
AndyNemmity 11 hours ago [-]
Which exact documents to you give them. The single style guide? The references as well? The additional detail listed in the guide as links?
I'm curious to try your proposal, I just want more specifics.
AndyNemmity 9 hours ago [-]
I've made a pr to my agent trying to implement it. it did fine in blind a/b tests so just going to go forward
When you give those resources to your coding agent, do you give them URLs? Or work with local versions?
I've found a lot of success pointing claude at locally downloaded docs over llms.txt URLs but not sure how to scale the pattern for a bigger project.
dizhn 16 hours ago [-]
A sort of an amateur I found Go to be really good when used with language models. Simplicity and tooling helps I suppose and I expected it to. However I was pleasantly surprised with how they are also pretty good with Flutter and Dart. Again good tooling, good documentation and perhaps not much historical baggage like a python or a PHP would have. And no stack overflow to speak of pretty much.
jdw64 17 hours ago [-]
I have a question: why do you think Go is better compared to other languages?
After all, learning a new language takes a lot of time. While basic syntax is common and quick to pick up, mastering a language's specific mental model requires a significant time investment, which is why I've used Go before but never seriously.
My interest was piqued recently when I heard about TypeScript tooling being ported to Go, and I know it is incredibly fast. However, where do the results claiming that AI agents generate superior Go code actually come from? Is it a fair, apples-to-apples comparison?
Since Go is a very small language with only 25 keywords, the way you write code is extremely standardized. Because of this, I would assume it naturally produces a lot of excellent best practices and conventions, but I'm not sure if there are actual, direct code examples proving this
jeanbza 17 hours ago [-]
> why do you think Go is better compared to other languages?
I didn't say that. :)
> where do the results claiming that AI agents generate superior Go code actually come from?
Like I said - reports from users.
> Is it a fair, apples-to-apples comparison?
No - these are reports from users, not a systematic analysis.
PrimalPower 16 hours ago [-]
>> why do you think Go is better compared to other languages?
> I didn't say that. :)
I call this the Go paradox.
I simultaneously believe we should reach for it 80% of the time to solve common collaborative problems. And being a poorer language is actually an asset in these cases.
However, in doing so, we get rusty lose our fluency in more expressive, perhaps even better languages.
wvenable 16 hours ago [-]
> Like I said - reports from users.
How does that work? Are they generating the same project in different languages and comparing the results? What does it mean for the code to be "better"?
jdw64 17 hours ago [-]
Ah, I see. I misunderstood.Is the report from an internal source, so it can't be shared? If not, I'd appreciate it if you could send me a link so I can look into it too.
jatins 16 hours ago [-]
it’s probably just some informal Slack messages between colleagues that is being described as “reports from users”. There is no Report here
jeanbza 15 hours ago [-]
Yes, this. =) I talk to Go users around the company all the time. Their feedback has been in this direction for a bit now.
switchbak 13 hours ago [-]
But isn't this expected from users that like a certain language? Won't you also hear this response from Rust users that like Rust?
frollogaston 11 hours ago [-]
Exactly. I only count opinions from people who have deeply used the two langs they're comparing and can express what exactly was wrong with one of them for their task.
zero_shift 16 hours ago [-]
You are being downvoted but I think this is correct. I doubt Netflix is really doing a double blind RCT on which languages produce better AI pull requests. How would that even work, have two versions of each service in different languages?
It's anecdata and maybe, MAYBE, a spreadsheet. Or a Google Form somewhere.
mbreese 13 hours ago [-]
Go is really amenable to being used to write code by LLMs. New code takes time to pick up, but the LLM is a quick study.
In my opinion, it has little to do with the speed of the language. The large quantity of source code to train on is quite helpful, but I think it's something else.
There are three things that I think make it well suited to LLM authorship -
1) static typing and a quick compiler - a variable can't change type after it's declared (unlike Python) makes Go more robust compared to dynamic languages. You (almost) always know what the type of a variable is. And the quick compiling with hard-stop errors means that the LLM gets a solid signal for each round.
2) It's quite opinionated, syntactically. There is generally one way that Go lang code is supposed to look. That means it's pretty easy to read as well as write. The lack of things like operator/method overloading make it an easy language to reason about.
3) the stdlib and limited dependencies. Dependency trees tend to be shallow, and because of the static linking (by default), you can generally be confident that what you wrote will run.
zarzavat 7 hours ago [-]
My calculus is very simple these days:
If I care about performance, use Rust.
If I care about iteration speed, use TypeScript.
If I want a script or numerical code, use Python.
LLMs are better with Rust because the more expressive type system provides stronger guardrails especially when writing multithreaded code. Go is almost the worst conceivable design of a programming language for LLMs: powerful but weak guardrails. Only C and C++ would be worse.
LLMs don't struggle with the low-level lifetimes like humans do. They struggle with the high-level view because of limited context windows. That's why you want a powerful type system to enforce those global constraints. Go ain't it.
CoolestBeans 16 hours ago [-]
I love the sleight of hand this blog post tries to pull off here. It doesn't matter than Go isn't fun to write because the AI is doing it now! Yeah so it sucked for the last twenty years? I know the main thesis is that Go is holistically good at software engineering so its weakness as a programming language is minimized. I've made a similar arguments that coding agents push the burden more into the other aspects of software engineering. But like, we all see what Google is doing here right? They want to declare that the rules have changed so Go's weakness transmutes into a strength. I'm also not buying it.
dimgl 10 hours ago [-]
I've never found that Go is not fun to write. On the contrary... Go is pretty refreshing with its simplicity. I found myself to be immensely productive writing Go.
CoolestBeans 10 hours ago [-]
For sure! Why is Google throwing their own language under the bus? They're literally saying in their article Go isn't the easiest language to write but that doesn't matter because its the best for maintaining a project. I also don't buy that readability and writeability are always being traded off.
badrequest 8 hours ago [-]
Where does it say it isn't the easiest language to write? It says the exact opposite in the second paragraph.
aryehof 5 hours ago [-]
One of the authors is a Google “Evangelist”. A “Chief” one to boot. Why would you expect different?
16 hours ago [-]
shevy-java 16 hours ago [-]
I agree with you here and I think you raise several good points, such as "Go's weakness transmutes into a strength" (allegedly). Indeed that makes no sense for Google to try to claim that.
Your other point is even more interesting, e. g. "before AI, Go sucked and nobody used it" - now this may be an exaggeration or simplification, but it is a great observation nonetheless, because Google suddenly tries to connect Go with the rise of AI, almost as if AI could not have risen without Go, which is indeed very strange as an argument to make by Google here. This also reminds me of Google promoting Dart/Flutter before giving up on this and preparing to send it (eventually) to the infamous Google graveyard at some point in the not-so-distant future.
llm_nerd 10 hours ago [-]
It pulls no such sleight of hand, and you have invented a wholesale strawman.
It's also simply poorly informed. Go is a fantastically enjoyable language to program in. In many ways that has been a bit of its curse compared to languages like Rust (which is legitimately a not fun language to write it, and which AI tools are also very good at writing), because keeping the language simple has hobbled some edge cases.
I don't write a lot of Go as my professional life has pushed me more to Rust, but Go and Object Pascal are easily the two most enjoyable languages I've ever developed in.
diego_sandoval 10 hours ago [-]
On the list of languages/ecosystems that make me want to rip my hair off, Go is way below.
Javascript takes the throne on that one.
a2ff6eeb0 11 hours ago [-]
Are they wrong? If we're copy-pasting errors from applications into claude without looking at the errors (and, that is the future of generating code), why do you care about the language that's being used, outside of the LLMs being good at them?
I don't have serious metrics about if Go is better or worse than others, but LLMs seem to do fine with it.
Havoc 15 hours ago [-]
This would have been more credible coming from someone other than the creator of the Go language.
I'm personally leaning into rust for LLM. The whole fussy compiler & errors surface at compile time seems IDEAL for LLMs for me. Hammering compile with tokens is a way better strategy than trying to deduce where stuff may fail at run time and try to catch it via tests.
Tokens are cheap, surprises at runtime are not. So a super anal compiler is what I want. I've looked at lean4 too as the logical next step but not confident I can guide an LLM competently enough for that.
igravious 14 hours ago [-]
fwiw I have a bunch of LLMs writing first Lean code and now Agda code.
My observation. LLMs find reasoning about Agda as difficult as I find reasoning about C code. I've thrown a lot of gnarly C and Ruby code at all sorts of LLMs and they have only gotten more and more impressive as frontier models have gotten stronger. With Agda, they're like "hmm, tricky" whereas for me it's an impenetrable fortress. I've asked them why they find Agda so much more difficult to write (and why they have to iterate and reiterate many many many times until they get to a destination whereas they can one-shot and two-shot C and Ruby and they tell me its the multiple competing constraints. GLM is hilarious, it flat out refuses to write Agda code but it reads it well enough. They all read it well enough. Fable is obviously great at it. And Opus 4.8/5.0 are great (if they stay on track and don't sneakily go their own way) but they're too annoying to talk to. On balance Kimi K3 is the best balance of not annoying, relatively cheap, and strong -- great model all round tbh.
So yeah, interesting I've discovered the limits of their ability coding-ability-wise. None of them are that good at designing/aesthetic judgment/architecting so thankfully they still need me in the loop.
mac-mc 10 hours ago [-]
A huge amount of it is also the amount of training data. Agda will have little training data so the result will not be nearly as good.
I did a shoot out of making AI make the same simple desktop app from a SwiftUI reference for 30 different language & desktop framework combinations, and by far the best implementation came from the electron web typescript one. The least amount of LoC, the best and most complete implementation and the fastest to implement.
RealityVoid 10 hours ago [-]
> My observation. LLMs find reasoning about Agda as difficult as I find reasoning about C code.
A bit funny, because I thought... Hmm, so LLM's find Agda natural?
My point being... It's a matter oh habit. After writing C firmware for more than a decade, I can read C easily. I might have to think of some parts and trace the code. But I can grokk it and hold the thing in my head. With Rust on the other hand, I just don't feel it as well. I am afraid writing C gave me brain damage and restricted the lens I can see the world through.
14 hours ago [-]
Havoc 13 hours ago [-]
>fwiw I have a bunch of LLMs writing first Lean code
How do you bridge the mental gap?
The gap between me writing high quality rust do this steps and something being logically sound seems enormous to me
Maybe I'm misunderstanding things but I just can't articulate my ideas in casual lean4. But i can do casual rust spec
gr_norm 11 hours ago [-]
As someone experimenting with this, it's definitely very difficult to articulate your ideas using advanced type systems. At the same time, the process of doing it often forces me to seriously think through what I want the code to do, which I've noticed qualitatively improves the end result and my understanding of it.
My advice is to be okay with starting small: don't go for full end-to-end correctness or anything like it. Just think of simple properties you want like 'the list returned by this endpoint should always be sorted in ascending order' or 'this operation should be idempotent' and go from there. Use your favorite LLM to help come up with example specifications from natural language, as a starting point, and try hard to fully understand those.
This kind of work does operate at the frontier of what LLMs can do, so expect to run into roadblocks (wasting tokens proving accidentally hard properties, etc).
CopyOnWrite 15 hours ago [-]
I disagree.
LLMs fail to produce bug free concurrent code even for very simple cases.
Golang lacks the ability to build descent abstractions, not even mentioning the wild west of additional tools and libraries needed for non trivial micro services.
For me it is a red flag, that LLMs allow people to produce more bad Golang code faster. This is only optimization for companies which can afford enough software developers to review the excessive amounts of code needed to solve trivial problems in Golang, which are builtin in every descent programming language and/or framework.
Use LMMs and use the right programming language. This might be Golang, but most probably it is C#, Java, Python, Ruby or even PHP. (Or Rust, C, D, ...)
Groxx 9 hours ago [-]
Broadly agreed, the concurrent Go code I've gotten out of them has been absolutely riddled with issues, and they're even worse at writing tests for it. They can get tutorial-level code on the first shot almost always... but tutorial-level Go code is often rather unusable in production due to missing error handling or observability.
Go's generics are getting a fairly important improvement soon though! Generic methods, finally! It should help open up some more ergonomic patterns: https://tip.golang.org/doc/go1.27
a2ff6eeb0 11 hours ago [-]
Ask them to debug. LLMs are acceptable at writing code, but they're really good at spotting bugs in code that's already been written. What kind of results do you get if you tell them to look for bugs with a clean context subagent?
In my experience, LLMs are excellent at finding concurency bugs.
treyd 7 hours ago [-]
Debugging concurrency issues isn't a syntactic process so they have to resort to println debugging. This works but isn't exhaustive and burns a lot of tokens.
a2ff6eeb0 5 hours ago [-]
They do a fantastic job just by inspecting the source. It's obviously not exhaustive, but it's quite good.
Test it on your last concurrency bug. Point fable at the rough symptoms and ask to find where the issue is by inspection. It'll probably do just fine.
dgunay 17 hours ago [-]
I like Go but a couple of these "advantages" wash out when you add the scale and typical usage patterns of agents.
| Go is Readable / Go is Maintainable
It's true that Go, as a low-magic language, tends to be very same-y looking across projects, which is incredible for being able to reliably understand your dependencies' source code. And its tooling is world-class. I love this about Go.
But in practice I've found that, working in a monorepo with multiple teams, contributors that don't have cross-team legibility as a priority will just write SO much more code. And with business logic, often the fact that I can read the code on a line-by-line level doesn't matter if I don't understand the wider context to know how something might effect spooky action at a distance.
Pre-agents, I witnessed a fast transition from a codebase that I could mostly hold in my head to one where large swathes of it had been written and rewritten until they were unrecognizable to me. Now we have agents and, since they are still mostly not good at software engineering in-the-large, the process of knowledge debt accumulation (and ofc tech debt accumulation) in a codebase accelerates tenfold without concerted effort in the other direction. Go being easy to read does not intrinsically help with that.
recursivecaveat 3 hours ago [-]
My problems reading code are understanding what the new vocabulary actually means, what it does in context, why it exists, etc. Doubly so when someone is pinging me to review a new 13000 line AI MR every 24h. Understanding an individual line because of some complex C++ feature, I don't remember it ever being an issue.
Buttons840 17 hours ago [-]
I'd argue Go is not on a "Pareto frontier" and that no matter how you value the various attributes of programming languages, a fair assessment will never select Go.
A simple example is: if you highly value language popularity; Go is not most popular. If you highly value a type system that catches errors; Go's type system catches fewer errors than others. Etc. There is no weighted sum of attributes that will select Go--that's my argument.
runjake 16 hours ago [-]
Here's how my assessment selected Go (long before LLMs):
- I had to write a moderately complex program. I didn't want to do it in C, and I didn't want to learn Rust.
- So I spent roughly about 2 hours becoming familiar with Go and playing around in Go playground. I decided that this would work.
- And then I got started on my program and I was immediately productive and that software is still running today, along with all the other stuff I've written since then.
Programmer productivity is excellent with Go. And it has a thriving ecosystem. Of course, some things could be better, but I don't really have much issue with it's error handling or types.
super_flanker 14 hours ago [-]
> long before LLMs
I thought this thread was about an ideal language for LLMs, no?
unscaled 7 hours ago [-]
That's my take. The arguments for Go over Rust used to be:
- Better concurrency story
- Native cross-compilation of static binaries (great for CLIs)
- Easier to learn, easier to teach
- Opinionated: You don't have to enforce a single style everywhere
Concurrency died out as an argument when Rust async/await got better. Sure, it has "function colors" and that matters for weird purists who care very much about typing a single "await" in their code, but don't care at all about typing "foo, err := bla(); if err != nil { return err }" all over the place. But it doesn't matter in practice, and tokio has far better concurrency tools: there ares separate channel for mpsc, oneshot, broadcast and watch scenarios, there Streams, JoinSets and a select! macro that can operate more than just channels.
The static compilation argument also died pretty early on when the Rust musl target became more mature. It's still slightly easier to get cross-compilation started with Go, but now that you we have LLMs we wouldn't care.
The learning curve argument is dead. It used to be harder to hire or train Rust programmers and that was a real pain. But LLMs don't care. The same goes for the "Go is built for software engineering" argument, which is a euphemism "Go is our way or the highway level of opinionated". LLMs do not need an opinionated language as much as humans do. If you want all code to follow an arbitrary standard, just ask your LLM to set up one. Engineering teams used to spend years bikeshedding things like brace styles and spaces vs. tabs and Go went ahead stole that opportunity from them. But this is no longer needed.
speed_spread 16 hours ago [-]
> I didn't want to do it in C, and I didn't want to learn Rust.
Sounds like you made a decision right there. The rest is just retro-justification, not a logical argument or comparative between options. It works for you, good.
geodel 14 hours ago [-]
Retro-justification is not some flaw it is most common way people choose tech stacks.
The only logic that matters most of time is business logic of solution serving problem statement and not logic of choosing a technical stack.
stouset 4 hours ago [-]
The original point was that go is not a Pareto-optimal choice along any set of language criteria.
"I didn't feel like choosing $LANG's competitors, so I went with $LANG" might be how languages are chosen for projects in the real world, but it's not exactly a convincing rebuttal to the argument being made.
genxy 10 hours ago [-]
Post hoc rationalization
The choice we made for other reasons is the best one for these constructed reasons that didn't exist until later.
It was and is a logical argument. Both C and Rust are much harder to learn.
ratscylla 16 hours ago [-]
Something doesn’t need to be the best at anything to be on a Pareto frontier. And (usually) no one chooses on a single dimension; they choose a point in many that maximizes distance from zero, scaled by their preferences, if you are thinking of it like a frontier.
Buttons840 16 hours ago [-]
Yes, you're technically correct (the best kind of correct).
I guess if you consider enough attributes or "dimensions" then any programming languages will be the furthest in some direction, including Go.
henrymerrilees 16 hours ago [-]
Is there a language that you would argue is at least as good as Go at everything and better than Go in at least one thing? That would be the most straightforward way to argue against its Pareto optimality.
Listing particular sets of preferences for which Go is not optimal is not sufficient unless you can show the list to be exhaustive.
frollogaston 4 hours ago [-]
None. But the very latest Java with records and virtual threads might be close to that for application code, cause it's like Go with exceptions and allegedly better generics.
odo1242 15 hours ago [-]
I'm not GP, but for me that would be TypeScript. TypeScript's tooling is as good as Go's across the board, it's very readable, it's a simple language, it has very few footguns, and it compiles fast. But it has better type safety than Go.
This isn't an exhaustive proof as no language will every be fully Pareto optimal in practice (it's just not possible, there are too many dimensions), but I'd argue it's at least somewhat close.
frollogaston 4 hours ago [-]
Go was originally designed as a systems language to replace C++. It's much faster than JS but also less suited for applications code in some ways. JS (or TS) is definitely not strictly better than Go or vice versa.
One less obvious advantage: Go has greenthreading which is better than JS's async-await. Rust chose async-await to avoid the runtime overhead of greenthreading, but JS has no such reason, it's just a downside.
amazingamazing 11 hours ago [-]
Since when did does typescript compile faster than go? I do agree typescript is a good alternative but it is very different.
anon7000 5 hours ago [-]
As someone who’s written huge amounts of Typescript, and no Go… the JS/TS ecosystem is absolutely atrocious. I’ve worked on developer productivity teams for almost a decade and JS tooling issues are a never ending battle. Every upgrade to major dependencies almost anywhere in your stack will 1. Include breaking changes and required migrations, and 2. Will also force you to update other dependencies for compatibility, which may have their own breaking changes and so on and so forth.
The tooling will let you do whatever you want, but the lack of standardization is very poor. Even now, many are switching from Eslint to Oxlint. Or Jest to Vitest. Or tsc to faster build tools. There is massive fragmentation.
I frankly yearn for a language that is always backwards compatible (JS itself might be, but ESM/CJS/etc. won’t be because the language relied on 3rd party/runtime-provided methods of importing modules for so long…), and actually has standard basic tooling from the start. Along with halfway decent security posture towards dependencies. And no need to manage a runtime. And produces smaller images.
Like if it’s just about the language, sure TS is extremely usable, async is extremely easy because it’s not a real thread, etc etc. But has plenty of quirks due to being tacked on top of JavaScript. (For example, being forced to import typescript from “.js” extension and not “.ts” with certain normal compiler settings…)
eudamoniac 7 hours ago [-]
Typescript is single threaded and 2-10x slower and does not compile into a binary.
anon7000 5 hours ago [-]
Funny enough, the Typescript 7 compiler is no longer single threaded because it’s (ironically) now written in Go, not Typescript.
frollogaston 4 hours ago [-]
Pareto frontier means they can't improve one aspect without hurting another one, not what you're describing. But I would say Go isn't on a Pareto frontier because the error handling is plain bad and could be fixed without any loss.
everforward 15 hours ago [-]
Go is relatively easy to learn, and the semantics of the language make it more difficult to write "clever" code that's difficult to understand.
That's the main selling point, with a secondary point that it statically compiles so you don't have to do a whole Python/JS distribution thing for CLIs.
Java feels like the closest contender here, although it really sucks for CLIs due to start up times. I don't think it's the easiest to learn either, but I've never tried all that hard.
It only really makes sense to me at org-scale, though. I think you raise a very good point for individual projects, I too normally don't choose Go for that (unless I need compilation to make distribution to myself easier on corporate laptops).
stouset 4 hours ago [-]
Choosing a language because it's easy to learn might be common and popular, but that is just about the least meaningful criteria for a programming language given the length of time you expect to use it.
Can you imagine if structural engineers rushed to post comments about how they decided to use wood for all their projects because it was simple to get up and running with, and they didn't want to have to deal with the all complexities of having to learn about metals like steel?
za3faran 10 hours ago [-]
Java has GraalVM which compiles to native code if you care about startup time.
groestl 16 hours ago [-]
Simple toolchain which supports trivial lightweight deployment is my go to attribute to select Go in projects.
aabdi 12 hours ago [-]
Uh compile time and linting efficiency, lightweight runtime, gc.
There’s no equivalent competitor, it’s the best if u want to just write lots of undifferentiated code.
To caveat this if u want to run about 50 agents or so in parallel, all the typescript projects burn ur disk via node modules. The rust ones take forever to compile and burn too much compute
za3faran 10 hours ago [-]
Java and C# (JVM and .NET in general) are favorable here.
aabdi 6 hours ago [-]
Uh at the very least Java is bad. the java programs we run take 4 gigs and burn my entire compute. Every1 used spring or guice and the di runtime, so tests are expensive for e2e with mocks. There’s no scrutable way I can run more than 2 or 3 on a standard laptop without burning out the thing.
Go can.
KptMarchewa 1 hours ago [-]
You don't have to use Spring or the typical enterprise IOC that plagued 00s and 10s Java.
za3faran 2 hours ago [-]
That could be a Spring issue then, not Java. Do you run with -Xmx specified?
aabdi 12 hours ago [-]
Uh compile time and linting efficiency, lightweight runtime, gc.
There’s no equivalent competitor, it’s the best if u want to just write lots of undifferentiated code.
ignoramous 16 hours ago [-]
> if you highly value language popularity; Go is not most popular
Go is similar to popular languages like C, JS/TS, & Python. And so, easy to get started.
> highly value a type system that catches errors
Probably these folks already use even less popular ML-style languages like OCaml & Haskell; or (comparatively) obscure ones like Agda, Idris, & rocq/Coq.
odo1242 15 hours ago [-]
Or Rust, Swift, etc.
switchbak 13 hours ago [-]
I wouldn't take language advice from a Product Manager and Chief Evangelist from anywhere - and especially not Google.
Having said that: my opinion is that LLMs thrive by working in a tight loop. Unlike a human, they thrive with more and tighter constraints (and the better models are obviously far better in this regard).
I want to ditch the things that made writing code easier due to the limitations of humans, and embrace something that an LLM can leverage for better results. For me that means: an especially rich type system, (ideally pure) functional code, efficient systems-level performance and leanness. Good error messages that guide the LLM incrementally.
Go does not provide much in the way of those 3 desires, so calling it "ideal" with nothing aside from anecdotes to back that up is not compelling.
fractorial 8 hours ago [-]
I can’t say much for a Chief Evangelist, but the Product Manager certainly has quite the C.V.
cztomsik 3 hours ago [-]
I will leave this prediction here and maybe come back in few years:
1. JS is mem-safe, single-threaded, and there are lots of training data. Easily my first choice. I'd put Python here as well, although I don't like it personally. Both should be used with "avoid external deps" in your AGENTS.md
2. Go might be a good second choice. Simple language, IMO good primitives for concurrency, well-designed std, therefore smaller potential for supply chain attacks.
3. Elixir/Erlang, little training data but rising. Safe language, safe concurrency, immutable, scalable, there are some many advantages... It has been avoided because it's different but that could change drastically in the age of LLMs.
4. Rust is probably next choice, along with C++, because while Rust is safer, the language is quite complex. C might be here too, there is a lot of training data, but every project is different and the language is very unsafe.
5. Zig, I really like the language, but it is terrible for LLMs, mainly because it's constantly changing, and the std is also under-featured and IMO weirdly designed. It's a fun language for hobby hacking, which I believe is not going anywhere, it's just not going to be something you will be payed for.
rio517 3 hours ago [-]
I mostly use Elixir and JS, and I'm constantly surprised by how much easier and better the code quality is in Elixir, especially given the much smaller training data. I've started to use it for all my personal projects. I think Elixir's terseness, introspection capabilities, and strong ecosystem-wide quality guards really help.
At work, we use C#. I'm shocked at how much worse it is. I've also used a bunch of Python, but I still feel the quality isn't as good as the codebase grows, but I didnt put as much effort trying to improve it.
za3faran 2 hours ago [-]
What issues are you seeing using LLMs with C#?
hugodan 17 hours ago [-]
Who cares? Languages are tools, LLMs are tools. Use the ones more appropriate for what you are trying to do.
Is Go better than CSS if you are doing web layouts? Is it better than zig if you are outputting minimal wasm deliverables? Is it better than swift if you are doing iOS specific development? Is it better than bash for OS scripting?
Think about what you are doing and choose appropriately. This was true before LLMs.
Are you having fun? Chose LISP then
runjake 16 hours ago [-]
> Who cares? Languages are tools, LLMs are tools. Use the ones more appropriate for what you are trying to do.
The article specifically discusses how Go is well-suited for LLMs. It's not going on about general programming topics.
hugodan 16 hours ago [-]
So you are using Go with LLMs for the objective and destination of token consumption for token consumption sake?
what would be the purpose then?
ffsm8 16 hours ago [-]
Read the article to find out.
Token use didn't seem to be a criteria from my casual reading, but maybe you can illuminate me what section pointed to that, I may have been too superficial in my reading
hugodan 16 hours ago [-]
Do not assume I haven't read.
runjake 16 hours ago [-]
> Do not assume I haven't read.
It's hard not to, given your comments in this thread.
redmoonx 8 hours ago [-]
"Never assume a man hasn't done what he hasn't said he hasn't done" -Philipesians 22:19
frollogaston 14 hours ago [-]
The article is about which tool is more appropriate, and you're dodging that question. Every use case has multiple langs you could use for it, and there's no universally agreed-upon choice. Like if you're writing a typical web API backend with LLM assistance from scratch, which do you use between JS, Py, Java, Go, Rust, etc?
win311fwg 17 hours ago [-]
> Is it better than zig if you are outputting minimal wasm deliverables?
Which tradeoffs are you willing to accept? Zig (along with several other languages) is superior in a lot of ways for that type of job, but I still settled on Go for a particular minimal WASM (browser) project. It wasn't my first choice, but it was where I ended up because LLMs kept going out to lunch in other languages and I didn't have anywhere close to the required budget to write it by hand. I read some comments like these about Go in the past so the Go attempt was mostly a contrarian Hail Mary after so many previous failed attempts in more technically well suited languages and... it worked! Shockingly well.
It still isn't my first choice for it, but having something useful with happy users beats technical imperfection every day of the week as far as my needs go. Go really did show its worth as an LLM target for that particular workload. Whether or not that is reproducible for any other project remains to be seen, but there seems to be a growing sentiment that echos the same. There just might be something to it.
kristianp 12 hours ago [-]
Curious what kind of application you used wasm and Tinygo for? Obviously not the kind of app that an LLM would usually spit out a bunch of react for.
hugodan 16 hours ago [-]
the Go runtime comes along for the ride when producing a wasm file, if you are interested in "minimal" (as in small or without extra cruft) then languages that do not require such a thing might be more adequate
win311fwg 16 hours ago [-]
Tinygo's base runtime is only around 10kb. It was minimal enough for my needs. gc's runtime would have been a non-starter for that task, to be fair, but Go isn't an implementation. It is, quite explicitly, a language.
There are language implementations that would have been more minimal than that, sure, but there was no obvious way to get LLMs into alignment. I tried. Multiple times. When I switched to Go, it just worked. It may not be technical perfection, but it let me ship something I had almost given up on and it has satisfied users. The tradeoff was worthwhile for my needs. That tradeoff may not be acceptable in all cases. Hence what is best being meaningless without at least defining which tradeoffs you are willing to accept.
hugodan 15 hours ago [-]
If TinyGo works for your codebase, and those 10KB are something you can live with, then perfect.
Two things to keep in mind here:
1. TinyGo is not Go, more Go-like or adjacent
2. 10KB still matters a lot in a lot of minimal target/usage scenarios
win311fwg 14 hours ago [-]
> TinyGo is not Go
Exactly. Go is a language. Tinygo is an implementation, like gccgo, gc, llgo, etc. Just as gcc, clang, and msvc are not C.
> more Go-like or adjacent
It is true that recover isn't fully spec complaint at this time. That's not entirely unusual for an implementation, though. msvc is famously not 100% spec complaint with C, but Microsoft still officially considers it a C compiler, as do most who use it to compile their C code. There is usually a little grace given.
It is not like Solod that is Go-like but trying to do something quite different. Tinygo is intended to be a proper Go compiler implementation and has achieved that, aside from the recover situation.
> 10KB still matters a lot in a lot of minimal target/usage scenarios
But, of course, if the LLM cannot wrangle the language then it doesn't matter. Nobody cares how large or small your program is if you never ship it. That only matters if you are using LLMs, but since that's what we have always been talking about...
frollogaston 14 hours ago [-]
"One of the things that most distinguishes Go is that it is not just a language, it’s a platform" according to the article
14 hours ago [-]
wltr 17 hours ago [-]
Been doing bash scripting for years. Tried Go recently, on my, it’s so much better for everything OS scripting. I regret I haven’t started with Go years ago. All my scripts are rewritten to Go. I kept only a handful, those that are just a few lines and no logic.
hugodan 16 hours ago [-]
I regret not going with bash or even sh when I had the chance. Nothing beats that for ubiquity and getting shit done.
Go is behind, specifically, you have no guarantees that a given machine has Go installed, and doing stuff like gluing commands together, inspecting some files, pipe output around, or automate the boring thing in 30 seconds.
Sure Go beats bash or sh when the thing you are doing starts to become real software, but that is a problem that sits between the chair and the keyboard.
wltr 5 hours ago [-]
That kept me away from the rewrite, but actually you can just throw a bin onto your server. At least for all my servers, I can do that. Migrating to Go helped me clean like hundreds of scripts into just a handful (tens) of slightly more complex, but unified programs with shared logic. I kept sticking to bash, not realising the complexity grew up already, and having a pile of simple scripts isn’t as simple as I thought. Go solved this beautifully, all the scripts were rewritten within just a month (with Claude assistance, but I’ve been checking on the code, it was OK), and now I can maintain them with less mental overhead.
transmit101 14 hours ago [-]
Having explicit and unavoidable error handling (which Go of course has in spades) is a particular improvement when writing/replacing Bash scripts.
soupbowl 16 hours ago [-]
Are you using 'go run' or compiling these scripts? Just curious about what you are up to as I was considering moving my scripts from bash to go.
transmit101 14 hours ago [-]
Not sure if it's obvious, but "go run" is just a thin wrapper around "go build" which compiles your Go code to a temporary location and then runs it in a single step.
wltr 6 hours ago [-]
Most of the time I use go build, or precisely make install with custom Makefile. For the one-time ad-hoc tools (vibe coded, by the way), I may use go run. My point is use the simplest tool, if it’s a little bit more complex than a few lines, it’s better in Go than bash. Here, I rather mean it’s better in any real programming language. Just… well, Go is really simple and with some GPT assistance you may be just one prompt and a minute away from automating some routine tasks. I try to automate as much as I can notice. E.g. I have a special script (now program) which moves files and directories from one location (synced documents) to another (archive on a disk). This is just a very simple operation, but doing it automatically feels very different. I’d highly recommend on trying something similar. Previously, I thought bash is good enough for this (and it is!), but Go is just better for me personally. And bonus thing, it works much faster.
lowbloodsugar 10 hours ago [-]
How dare you suggest having fun! Pay attention! We’re trying to have a language flame war here!
hugodan 3 hours ago [-]
Hahah thanks for noticing that, also Lisp in all caps, like the original from the 60s
jibal 15 hours ago [-]
> Who cares? [sorry, but that question is trolling]
People who want to use the most appropriate tool.
> Use the ones more appropriate for what you are trying to do.
What they are trying to do is find a programming language that LLMs work well with.
> So you are using Go with LLMs for the objective and destination of token consumption for token consumption sake?
The trolling gets more intense with each comment ...
P.S. Someone else responded:
> But this isn't a user story. The user story is what you should be picking the tool for.
I don't see how this is at all relevant to my comments. I'm certainly not going to argue about what some other party should or should not be doing.
philipwhiuk 15 hours ago [-]
> What they are trying to do is find a programming language that LLMs work well with.
But this isn't a user story. The user story is what you should be picking the tool for.
rudedogg 16 hours ago [-]
I keep seeing these language specific proclamations, and they are annoying and reek of inexperience to me.
I’ve had a great time doing LLM assisted coding in Zig, and it seems comparable to the generic Typescript/React I do at work.
I don’t doubt simplicity and good PL design pay dividends, but everyone’s favorite language can’t be the silver bullet in our new LLM world. Things just don’t add up, and I keep seeing it for Erlang, Gleam, Lisp, C, Rust, Go, TypeScript, Python, etc.
And to pick on Go a little bit, I don’t think it has any unique qualities that make it better for LLMs, where I think you could make that argument for other modern languages that offer new features leveraging their compilers and enforcing more correctness guarantees.
anthonypasq 14 hours ago [-]
compilation time is massively important for developing with agents
rudedogg 14 hours ago [-]
I agree.
It would be neat to see a matrix of compile times vs. language features, showing things like:
- Bounds checks
- UAF prevention
- exhaustive enums
- test speed
But I think even among those the subtleties would make a fair comparison impossible.
Anyway I think this is all very nuanced, and anyone proclaiming language X is the language to use in 2026 lacks the experience/knowledge to consider these trade-offs and can safely be ignored.
bygosh 7 hours ago [-]
do people actually claim LLMs are good with Lisp? all i've seen recently are people frustrated that their model can't seem to balance parentheses.
MeetingsBrowser 15 hours ago [-]
> leveraging their compilers and enforcing more correctness guarantees.
The counter argument here is that these checks cause slower compile times and were designed to prevent common mistakes humans make.
If models get good, they may not need the same checks human written code needs. For example, frontier models already will virtually never produce a typo.
Humans need time to think, but a model’s bottleneck is in how quickly it can verify its work. Slower compile times hurt a models ability to iterate.
I don’t think we’re there yet (and we may not get there). But there is an argument to be made that languages with faster compile times may be better for LLMs in the long run than languages with strong checks but slow compilation.
"After 7 years in production, Scarf has reluctantly moved away from Haskell"
And moved to Python, pretty much for the reasons you stated
gr_norm 14 hours ago [-]
This is a rather poorly-written post that more or less boils down to "GHC isn't fast enough to let us make deep-reaching changes to our codebase all the time" (fair, but this shouldn't be necessary if your abstractions are solid? seems to telegraph very substandard engineering practices, but I guess that's what you get with vibecoding) and vague complaining about how the Haskell community isn't all-in on AI.
I was curious about this so I dug further, and by the author's own admission, they've only made the switch for basic CRUD logic without performance needs, not their core services: https://news.ycombinator.com/item?id=48865986.
It's also pretty unsurprising, given what we know about LLMs' style transfer abilities, that transferring parts of an existing Haskell codebase into Python would avoid a lot of the errors and pitfalls that codebases originating in Python are known for. From my experience writing lots of Python, this does not continue to hold true as you let the agents loose on your Python codebase.
boredumb 16 hours ago [-]
I really don't agree. I'm not hear to evangelize rust but by using enums from DB to templates and writing the code to make it consistent my experience with LLMs is infinitely better than golang for consistency and you have to include a lot more context to make golang work without issues whenever things are operating on chans or workgroups.
tpoacher 16 hours ago [-]
"Oreo cookies are the tastiest cookies currently in the market!"
~ Oreo cookie company.
caleblloyd 10 hours ago [-]
Oreos are an ideal cookie in a milkshake machine fast food era
natsucks 16 hours ago [-]
yeah the conflict of interest here is staggering.
jryle70 13 hours ago [-]
Isn't that true? Prove them wrong.
(Someone who doesn't even eat cookie but heard a lot of praise of Oreo)
frollogaston 4 hours ago [-]
Pretty good proof is that people pick them apart to eat the inside, and they even acknowledge it.
steve1977 5 hours ago [-]
Oreo is mostly praised in the USA. Which says more about the USA than it says about Oreos.
jryle70 3 hours ago [-]
Interesting. Why is Oreos sold in over 100 countries and apparently sold very well?
steve1977 2 hours ago [-]
Because it's a famous brand and most people are sheep. Not because it's known for good quality or taste.
colwont 14 hours ago [-]
nailed it
amiune 17 hours ago [-]
While I somewhat agree I can’t tell if this is advertising from Google or a way to induce LLMs to think that Go is the ideal language.
bensyverson 17 hours ago [-]
Probably both, but I have to add: I agree with the post. I've done a ton of agentic development using Go over the past 6 months, and it hasn't let me down. You may ask "why not Rust, or Zig, or ____?" The reasons boil down to this:
- There's a lot of Go code out there which the models have seen, so they know how to write it.
- Go has an exceptional standard library, so you don't need to drag in 100 dependencies to create a simple web app.
- Go compiles extremely quickly for incremental builds, which really matters when agents are building and running tests constantly.
- Go has a goldilocks blend of performance and safety. You get a good type system and excellent runtime performance without forcing the model to spend cycles fixing Rust lifetimes or Swift concurrency issues for a marginal incremental gain.
- Go is relatively stable, so the LLM's memorized knowledge is still pretty fresh (as opposed to something like SwiftUI, where the API changes rapidly).
dralley 17 hours ago [-]
I don't think Rust is particularly worse than Go in any of these respects.
- LLMs have clearly been trained on a lot of Rust as well
- Compile times are counterbalanced by strong compiler with excellent error messages, and "cargo check" can catch many issues without a full build.
- If you're willing to accept Go levels of performance from Rust, there's nothing preventing you from using copies and clones rather than borrows, which makes most code dead simple.
- For most major dependency types, there exists a clear "winner" in terms of community adoption, so the fact that it's not in the stdlib is not that problematic.
bensyverson 10 hours ago [-]
I do not think "good error messages" is an even trade for "fast compile times." What happens is the LLM catches the error, then may hit another error, and try again. This leads to more tokens and more latency, and then after all that you have a longer compile time.
With that said, I have not done an extensive amount of agentic development in Rust, so maybe I just don't have the reps to compare fairly.
nylonstrung 7 hours ago [-]
It's less that the error messages are just "good" with Rust, it's that more stuff gets caught at comptime, and many of them can be autoremediated by cargo fix or the compiler itself says exactly what should be changed.
Nothing costs more tokens than an LLM trying to debug errors caused at runtime which doesn't map well to it's "intelligence" compared to what Rust provides
codexon 13 hours ago [-]
Rust compiles way slower in my experience. This is a major problem because ais need to recompile many times especially when it keeps running into borrow checker problems.
With golang, all borrow checker problems go away. This is a good trade off if your app is not cpu-bound, which most are not. If you need every last drop of performance then rust is a better choice of course.
However, I have run into a few cases of runtime null crashes in go.
dralley 13 hours ago [-]
> and "cargo check" can catch compile issues without a full build.
You only have to compile when you actually want to test the behavior, which tends to be right on the first try more often as a result of the strict compiler.
joseda-hg 16 hours ago [-]
How would you compare it to C#?
Stable-ish
There's a lot of documentation and plenty of stablished patterns, so LLM can produce it no sweat
Everything and the Kitchen Sink
Performant, and safeish, even if not null safe
keithnz 8 hours ago [-]
In my experience C# works out pretty good. I wrote a project in Go, it mostly went well, but it had weird bugs and the AI struggled to solve them. Rewriting in C# seemed a lot more robust. I use it a lot these days and I find the AI rarely has any issues with language/framework and you get pretty good results.
bensyverson 10 hours ago [-]
Yeah, C# is probably the closest direct comparison. I like that Go emits a simple binary, whereas it seems like that needs to be configured with a .NET project. Probably just a matter of taste/preference!
afdbcreid 14 hours ago [-]
I wouldn't call Go's type system "good". It's basic or less. It's sound, at least (in the presence of data races), but that is the case (or mostly the case) for most programming languages.
frizlab 13 hours ago [-]
SwiftUI has nothing to do with Swift… It’s just a UI framework that happens to have been written for Swift.
bensyverson 10 hours ago [-]
Fair—though SwiftUI has influenced/required new Swift features like Result Builders. I've found generating Swift to be a mixed bag. The LSP consistently reports stale errors which the model has to ignore, handling strict concurrency correctly can lead to ugly workarounds or huge refactors, the documentation for Apple's APIs aren't accessible to agents, the list goes on.
radicalriddler 16 hours ago [-]
Agreed. Felt like a AEO / or GEO (generative engine optimization or whatever the field term is these days) puff piece. Seems too verbose for most people to bother reading.
frollogaston 14 hours ago [-]
Gemini overindexes on Reddit answers. It'll give me clearly wrong info just because one person on Reddit said it. People are probably already bot-spamming Reddit for this exact reason.
17 hours ago [-]
woggy 10 hours ago [-]
I think the right language for agentic coding is something that brings in more ideas from formal verification, in a way where the spec and executable code live in the same world. I don't really know what that will look like but that's my gut feeling as a non-expert. Specs can be written in a higher level language (not english) that verifies the lower level code at compile time. I think Dafny might be the closest we have at the moment.
blindseer 2 hours ago [-]
I can't help but think this is Google attempting to poison the training data for future LLMs to incentivize them to pick Go.
Rust or Nim are really the ideal targets for LLMs and will continue to grow. As LLMs write more code and as humans review less, it will be more important to have confidence that your code doesn't run into a weird one off runtime heisenbug issue.
fmind-dev 4 hours ago [-]
I'm using Go more and more for my projects (AI, Web, CLI, ...). This is my go to for all my new projects.
My background is in data science and MLOps, where Python rules. But the focus is now less on building new AI models, and more on building the infrastructure and API calls with AI Agents. Go has a great async model, stellar performance, amazing tooling ecosystem, and far less ways of doing things than Python.
I except grow to become more and more popular, as our LLMs are now writing most of our code. Between a 50 MB portable binary in Go with 10x performance, and a 5 GB venv in Python with lack of proper parallelism, the choice is easy.
Myrmornis 10 hours ago [-]
> By enforcing a single, standardized format via the built-in gofmt tool
I'd read about this many times before I started with Go so I was particularly disappointed to learn that it was a lie. The most important task of a code formatter is to break long lines; it doesn't do it. It doesn't even have an option to do it!
frollogaston 4 hours ago [-]
Because long lines aren't against the style guide for some reason.
tracerbulletx 11 hours ago [-]
Agreed, my media server is mostly AI written go at this point and it works great. Before AI the "one way to do something" was already my favorite feature of go, now it makes it much easier for me to use AI and still understand my own project.
I use go for work and basically 100% agent-driven. I'd say using go with agents is a lot better than without. We use to have a consistent source of production errors where we forgot the pointer case in type switches (we'd pass a pointer to a struct where a concrete struct was expected and vice versa). AI hasn't made that mistake once in my experience.
That being said, the whole thing about go being "readable" is a little bit of a two-edged sword. Sure, it's straight-forward to read, but it's pretty verbose. And agents are good at producing a lot of text. The problem with reviewing go code for me is to see the forest for the trees. Subtle misunderstandings often hide in the vast amount of code that you have to read through while keeping the whole context in your head.
neprotivo 4 hours ago [-]
I am using Go right now for personal projects. One such project is to collect per-test-case coverage data and use it to study the structure of the underlying codebase. I'm hoping to develop a new knowledge base for agents to do feature location. Here's a demo https://atlas.vihren.dev
Anyway, it turned out that Go ironically makes it difficult to collect per-test-case coverage data. In spite of the standardized tooling it looks impossible to write a standardized collector that would run on most codebases. In hindsight using another language would have been a better choice
socketcluster 5 hours ago [-]
Plain JavaScript is the ideal language for AI coding. It's very good with complex architectures.
I think partly it's because the training set contains a lot of JS, but also because complex software written in JavaScript must have impeccable architecture in order to exist at all.
It's rare to encounter a complex, functioning JavaScript application with bad architecture. I've never met any engineer smart enough to maintain a large spaghetti-code JavaScript project.
On the other hand, I've seen horrible TypeScript projects. If it wasn't for the helpful type annotations, no human being would have been able to maintain it.
frollogaston 4 hours ago [-]
I have always preferred plain JS without AI coding too, partially cause of what you said. Typescript encourages bad code. It also gets in the way of good code, doesn't really prevent bugs in prod, and complicates the toolchain.
CSDude 15 hours ago [-]
I wish if err != nil return err was just 1 token.
Joking aside, as much as Go's stdlib and tools do the heavy lifting here, Go's verbostiy and expressing simple things in lots of lines worked against me most of the time.
I've had a really terrible time getting LLM to properly handle errors as return values. It seems that bubbling up errors, in a side channel, to a contextually relevant point in the code (exceptions) seems MUCH easier for LLM to reason about/implement properly.
Maybe my problem is I'm using a language with exceptions, so trying to go against the statistical grain, with return values, is just too much.
frollogaston 14 hours ago [-]
Exceptions are inherently better for high-level code, where basically every loc can fail and 99% of the time you only want to bubble that up. You only want errors as values in systems code, where exceptions would be landmines. Rust and Go both did that because they were at least originally designed for systems code.
Also, Go makes it way too easy to accidentally swallow an error. Rust doesn't have that problem.
Surprised by the negativity here. With or without AI, Go is a great choice for large software projects.
These have been my and friends' observations since LLM-assisted coding started picking up steam. Go's simplicity, consistency, stdlib and tooling seem to make it very reliable for LLM generation, and it was especially true during late 2025 / earlier this year when frontier models weren't as strong; might not be as noticeable now.
NegativeAbsence 49 minutes ago [-]
If ecosystem compatibility can be handled well, this seems perfectly viable.
imranq 9 hours ago [-]
Google doesnt even use its own Go build system internally. Its all blaze / bazel, so they are not even taking advantage of the so called compiler feedback of Go. Also if languages are to be designed for agents not humans, its not clear whether the verbosity of Go will help agents at all
roca 2 hours ago [-]
Too bad the RAM crisis makes GC languages like Go far less attractive.
mintflow 7 hours ago [-]
Nice article and some tenets have been said, such as software engineering is not same thing as programming.
As a long term C programmer and start using go from the early days, really love it's rich ecosystem and portability.
Nowadays, for any backend code, i just let agent to write using go, and for resource constraint environment, i just use rust.
And both have good C interop, and good ffi interface to hook into more higher level language such as Swift/Kotlin if one wnat to develop some mobile Apps
kstenerud 17 hours ago [-]
The killer feature of golang for LLM dev is the tooling.
forbidigo is what allows me to keep ambient config out of my app, and restrict file access to a small set of paths. The coverage tool has "nocover", so you can guarantee that every realistic path is exercised at least once ("100%" code coverage, which is not a marker for testing completeness, but rather for flagging code you forgot to test). Linting is really good as well.
The only thing I haven't found is something to enforce error handling. Rust is better for error paths because you're not allowed to ignore them.
xavdid 15 hours ago [-]
> Linting is really good as well.
Maybe we are using different tools (or we've set it up wrong) but I'm consistently surprised at how slow Go's linting is (using golangci-lint). Takes nearly 5 minutes on our codebase after any change (which means I just don't run it locally or in-editor). It's remarkable how poor the experience is after using tools like Python's Ruff (instant) or Rust's Clippy. I'd have expected a fast, default setup that I could tune.
Event JS's Eslint, which runs in actual JS, takes 21 seconds for a full sweep (which I don't normally run, since the in-editor hints are so fast)
It's surprising, because so many of Go's dev tools are so well thought out!
arccy 15 hours ago [-]
crappy third party tooling is crappy.
the author of the project just begs for money while only using linters written by other people
xavdid 15 hours ago [-]
Even using staticcheck directly is slow. Just very surprising- do all other Go writers not use a 3rd party linter (and just use `go vet`)?
jerf 17 hours ago [-]
"The only thing I haven't found is something to enforce error handling."
errcheck, generally as manifested in golangci-lint, ensures you can't forget to do something with them. It would be odd for you to know about forbidigo but not errcheck as the former is much less widely known; is there something that errcheck doesn't do for you?
It's worth pointing out that "discard this error on purpose" is a legitimate form of error handling, so "enforce error handling" can't really constitute banning that. That's not a Go statement, that's just true in general... it is sometimes valid to just ignore the error, because there's nothing useful to do with it anyhow. I would agree the ignoring should be explicit, but it is an option.
kstenerud 16 hours ago [-]
The rule I set for linting when an LLM is writing code is: Either you adhere to the rules, or you mark an exception with a valid reason.
Poor defaults break systems by a thousand cuts. They seem to make sense when designing the language (more convenient, less typing, etc), but then they very quickly become liabilities as project complexity increases. Go made the mistakes of mutable-by-default and silent-error-dropping, but their cyclical-import-forbidding was a good call.
jerf 14 hours ago [-]
It isn't entirely clear to me how that relates to what I said. errcheck prevents you from dropping errors or catching them but then overwriting them before doing anything else. There's a flag you can twiddle to throw a lint error on using underscore to ignore an error, too, if you're really perturbed about that. I have a personal rule to always have a comment explaining why it's OK to do that that predates AI coding rules. This seems to meet your criteria.
16 hours ago [-]
peterashford 9 hours ago [-]
In my experience using Claude code for Go and Java code, I've seen little advantage for one language over the other in the LLM agentic context. I did a little experimentation with Zig which was less successful. Presumably to do with the relative lack of documentation and still being a somewhat moving target.
That said, I have had Go concurrency code written with weaker models prove to be buggy, which shows up rapidly when reviewing with stronger models.
pmarreck 16 hours ago [-]
I disagree. I think WAT (WebAssembly Text), perhaps with some more niceties added, is an ideal language for AI-assisted software engineering.
AI agents can only reason about a certain number of things at a time. Time (and tokens) they spend reasoning about how to create a stack calling convention in assembly is time they don't spend reasoning about business logic.
sunsetSamurai 10 hours ago [-]
In the last few days I've heard this same claim regarding other languages like Gleam and Rust for one reason or another that I don't know who to believe.
Retr0id 16 hours ago [-]
IMHO there's never been an overall "ideal language", and there still isn't, it's just about the right tool for the job. The only thing LLMs change is that you don't need to give quite as much weight to how well you know a particular language.
brunoarueira 16 hours ago [-]
I couldn't agree more, but the following sentence is a little biased:
> Gophers often speak of how they love that they can never tell who on their team wrote a particular piece of code—it all looks the same.
Multiple languages can have a degree of understabillity, but what matters most is context, because sometimes we need to code in a way to solve a specific problem like performance and it should be kept as is.
Another side subject I should add is about test coverage, although code is cheap, mainly because AI, guarantee that new changes to a stable code should continue to work as expected.
I worked on a few go projects with bad structure and some of them with really low test coverage (e.g. 8%), so part of the post resonates with me about we as software engineers should pursuit good architecture and other skills to allow long term maintenance.
liuliu 16 hours ago [-]
1. The syntax surface is smaller, allowing less LLM "creativity;
2. The error handling is mechanical, which LLM clearly prefers (LLM is already trigger happy about writing tons of throw / try...catch.. in other languages, doing tons of `if err` is just in it comfort-zone).
skybrian 17 hours ago [-]
Can't really argue with that, but In my experience, coding agents work quite well with TypeScript too. :)
radicalriddler 15 hours ago [-]
The issue I always had with Typescript, was that LLM's like to find the easiest way to get a job done on a micro level (they seem to like to find the hardest design patterns to implement on the macro level tho, but language agnostic). What this means for Typescript, is unless you place guardrails everywhere, they'll cast their way out of a compiler problem with as any, or as unknown and then casting later. You either end up with readability issues, or runtime issues leaking out.
Might be a skill issue, but I got frustrated with it on new projects constantly.
skybrian 11 hours ago [-]
I haven't seen that too much, but I do have guardrails. I use Deno and run 'deno lint' as part of the build. It doesn't allow 'any'.
Also, I tend to ask planning questions, like "how would you implement this" and "what would the API changes be?" I'm picky about API's. Lately I've been using Deno workspaces (multi-package repos) and tell it when to make a new package or a new entrypoint. Maybe that helps?
If I just ask for features and don't look at the code, it will definitely make a mess, though. (A working mess, but it takes a while to refactor my way out.)
redox99 11 hours ago [-]
They're improving but you definitely need both a strong AGENTS.md and also usually many LLM passes (one for implementing a feature, another one for code quality, large passes every now and then for major refactors, etc).
That's not really a typescript thing though, just an LLM thing.
11293za-qasf 16 hours ago [-]
Given the date and the recent DeepMind shakeups, this blog post is obviously ordered from the very top.
Pichai wants to eliminate engineers, and DeepMind wasn't fast enough or too noble for it. Now people need to be propagandized for their obsolescence.
frollogaston 14 hours ago [-]
Good luck if that's really the case, cause most of Google's code is not in Go.
jpgvm 2 hours ago [-]
It really isn't.
Poor correctness guarantees, especially w.r.t concurrency. Nil pointer. Why.
LLMs are like a magnifying function. Whatever you put in you get back 10x over.
In the case of Go, in goes verbosity, Nil pointers, poor concurrency and synchronisation primitives (or poor performance of the safe ones, leading to sync.Mutex everywhere anyway). Also Go prioritises local readability over global understandability which is a poor tradeoff for LLMs with limited context windows.
So the LLM generates absolutely monstrously huge amounts of very hard to review very likely incorrect code.
No thanks.
Rust > Go.
In goes powerful, terse type system. Strong correctness guarantees not just around memory and pointers but also data races. A tendency towards using the type system to model invariants instead of relying on procedural guards and runtime assertions etc. Producing denser code is an LLM feature, it increases context window efficiency. Similarily the typesystem takes something that the LLM can spend a bunch of thinking tokens on to create a powerful global constraint. This fixes the global reasoning/context problem by pushing it back onto the typesystem.
Depending on the quality of your robot you will get different quality of code out but the ceiling is much higher. With Go better robots don't help much, even the highest quality robots output insanely verbose Go. Sort of just like with people... sort of like the language was designed as a lowest common denominator tool...
For a seasoned Rust programmer the output probably won't be hard to review, it will be easy to look at the types and either say "yeah that should probably be correct" or "no robot, do better".
You simply can't actually review the output of the slop cannons with Go, there is too much, looking at a struct tells you almost nothing about how correct the thing likely is, etc. The tests don't help either because there is going to be 10x the usual amount of those too so trying to review those for correctness is the same Sisyphean endeavour.
pjmlp 4 hours ago [-]
Sure, because no human should be forced to manually write Go's boilerplate code in the 21st century.
YuechenLi 16 hours ago [-]
I wouldn't say Go is IDEAL for AI coding, but it certainly has the case for one of the best programming languages that currently AI uses. Go definitely has its share of problems for human authors because it's so verbose and boilerplate heavy, which means it's less of an issue with LLMs than it is for human coders. Rust is comparatively worse, because LLMs don't make the same coding mistakes that humans do that justifies the existence of the borrow checker, it only seems to get in their way, and they spend more time fighting Rust's infrastructure than writing code.
The biggest barrier to Go adoption seems to be Google's internal resistance to migrate C++/Java code bases to Go and refusal to admit that Go is an amazing application programming language and not really a systems programming language for bare metal OS/driver work. For example, one of the biggest barriers to Fuchsia adoption has been Google asking people to commit to Dart, I think Fuchsia would have fared a lot better as an Android successor/alternative if the official applications programming language just been Go.
(BTW Carbon isn't even a real programming language, it's still somehow stuck at 0.0.0.0 after 4 years of development which is honestly insane.)
Oh, so, little bit of self-promotion: if you like Go but is frustrated with the ergonomics of it, I would ask you to try out the programming language I developed, Oct, for LLM coding which you can kinda think of as my attempt at making Kotlin for Go's Java: It uses a codegen compiler and compiles to a plain Go binary, so it runs on everything that Go runs, and there is a lot of extra features as well: Rust style exhaustive tagged/payload enums/`match`, C#'s immutable records updated with `with`, exhaustive error handling easy parallel concurrency, xUnit.NET style unit test harness, TypeScript style compile time constraints, F# like SI unit system, Go code generation metaprogramming, etc. Would love to have some Go experts here on HN take a gander at it and provide some feedback.
> Rust is comparatively worse, because LLMs don't make the same coding mistakes that humans do that justifies the existence of the borrow checker, it only seems to get in their way, and they spend more time fighting Rust's infrastructure than writing code.
I have found exactly the opposite to be true: as always, people think they can write safe concurrent code without the machine checking them and end up getting it completely wrong in lots of subtle cases. Except the problem is now much worse because you're not even writing the code, or in many cases, reading it. I prefer a language with a type system that saves me from the review burden of closely checking (and pretty much always finding issues in) concurrency invariants. And even tells me a bit more beyond that about what the code is intended to do.
colwont 14 hours ago [-]
Was also going to say this. If anything, the borrow checker in Rust is more likely to save you from LLM issues, because it won't bloody compile.
efnx 15 hours ago [-]
Came here to say exactly this. If you’re not writing the code (or especially reviewing it) then we need stronger type systems and more checks and fewer legal programs. Might as well move all the way to Idris or some not-yet-invented language that humans would find very restrictive.
virtualritz 15 hours ago [-]
> Rust is comparatively worse, because LLMs don't make the same coding mistakes that humans do that justifies the existence of the borrow checker, [...]
That's a pile of bollocks, pardon my French. Source/proof?
And to the contrary:
I've been working on a TS codebase that calls into C++ native/wasm-compiled code for six months now. The code is mostly LLM written.
Over these last six months we had four use-after-free and two other ownership-related bugs in LLM-generated TS code.
Whereas we had zero issues of any such kind with LLM-generated Rust code that sits in another two native/wasm-compiled metacrates we use.
LLMs are not much better at ownership tracking than humans.
Especially if resource acquisition and release are far apart in code and/or somehow nested/stacked/non-straightforward.
afdbcreid 14 hours ago [-]
The problem with ownership tracking is that it's global. Humans are bad with global things, linters too, but LLMs are exceptionally bad at them due to the context window and (currently, at least) not knowing enough where to search. So yes I'd expect them to make the same mistakes as human and even more frequently.
lowbloodsugar 10 hours ago [-]
I feel like LLMs and vibe coding have opened up rust to the kind of script kiddie who would previously have been begging for help on r/javascript or whatever.
If there is a problem with global lifetimes then the problem is certainly the person driving (or not) the LLM. Global lifetimes? FFS. Rust is hard because writing services that don’t have bugs is hard.
LLMs are not currently able to vibe a sophisticated application or service in rust. If it tells you it can do it in typescript or python, the it most likely certainly has not and you will have a wonderful time in production. Rust will burst that bubble.
YuechenLi 13 hours ago [-]
I'm curious on what you mean by "TS use-after-free", because as you obviously know, TS is GC'd. I don't have access to your codebase of course, but it seems to me that it is an FFI/native code boundary lifetime bug in the binding between TS and C++/WASM, not part of the TS managed memory. Comparing TS to native C++ FFI and/or manually managed WASM resources interface vs Rust + Rust ownership checked resources interface is kinda comparing apples to oranges here.
And as other commenters here have said, Rust's main issue for LLMs is infectious lifetime propagation, where the borrow checker knows you violated a lifetime constraint but doesn't tell you how to actually solve it, so LLMs get error messages like:
borrowed value does not live long enough
cannot borrow `x` as mutable because it is also borrowed as immutable
lifetime may not live long enough
And instead of trying to reason through the ownership graph, they just take the shortest path to get these things to go away by bypassing the borrow checker entirely, which defeats the entire point of using Rust to begin with.
ameliaquining 8 hours ago [-]
Source? I haven't heard of that failure mode being especially prevalent. (Also, by "bypassing the borrow checker" do you mean unsafe raw pointers, Rc/RefCell, or something else?)
jaynetics 16 hours ago [-]
> Go definitely has its share of problems for human authors because it's so verbose and boilerplate heavy, which means it's less of an issue with LLMs than it is for human coders.
If the premise of the article is true, and I think that it is, that's quite the downside for AI coding with go. The premise being that reviewing now plays much more of a role than writing.
Personally, I'd rather review, say, a ruby oneliner that extracts specific row values from a csv file with filter_map, compared to 40 or so lines of go, many of which I'd have to check individually for possible mistakes.
ameliaquining 16 hours ago [-]
Go doesn't have any kind of story for incremental migration from C++ or Java; you are talking about rewriting all those codebases from scratch, which is an obvious nonstarter as long as engineering resources are finite.
IIUC Fuchsia uses Dart mostly for UI stuff and Go has never really tried to be competitive there? I don't see much of a reason to suppose this is a serious bottleneck to Fuchsia adoption, as opposed to the obvious reasons why it's hard to displace an existing OS with a huge install base.
foota 16 hours ago [-]
> "because LLMs don't make the same coding mistakes that humans do that justifies the existence of the borrow checker"
Citation absolutely needed.
YuechenLi 16 hours ago [-]
Sure, what I mean by that is that LLM makes different kind of mistakes than humans, they usually take the shortest direct route to accomplish their task. You can see that with the Bun Rust rewrite, I don't think any human coder would put as many `unsafe` and `Clone()` and `Arc<Mutex<T>` in their code, so a lot of time, they would just attempt to bypass the borrow checker if they see it get in their way.
ameliaquining 8 hours ago [-]
Bun is an unrepresentative example of a Rust codebase for this purpose because (1) it was a direct port from a memory-unsafe language, and (2) it has a major C++ dependency (JavaScriptCore) whose objects in memory are deeply entangled with its own in very lifetime-complicated ways, which is something like the worst-case scenario for Rust's model of memory safety encapsulation.
foota 15 hours ago [-]
Ah, so it's more that "LLMs just bypass Rust's safety" rather than "LLMs write perfect C"? That's a more fair argument.
nylonstrung 7 hours ago [-]
> Go definitely has its share of problems for human authors because it's so verbose and boilerplate heavy, which means it's less of an issue with LLMs than it is for human coders
I think boilerplate & verbosity is an even bigger drawback with LLMs than human coding since context rot and "Lost in the Middle" phenomenon has so much effect on code quality
It seems that LLMs benefit from semantic and syntactical density
sgt 16 hours ago [-]
So in terms of the mainstream languages, what would you say would be the most ideal language? (At least until Oct takes off!). Perhaps modern Java? .. Or even Zig?
YuechenLi 16 hours ago [-]
C#, only because of dotnet ecosystem and tooling is great. TypeScript is a dark horse candidate, it's a great language with a great ecosystem trapped by JS tooling, and most of all, NPM. Rust is fine if you just tell LLMs to use short borrows only. I wouldn't even say Oct is the most ideal language, it's pretty good at getting LLMs to do science, but probably isn't the right language for all applications.
I have some very heavy criticism for Zig technically, because their whole thing about "no hidden control flow" becomes "shove all the hidden control flow into a second hard to debug runtime that runs at compile time", and manual allocation for everything is incredibly tedious and hard to keep track of in production code. I mean, C++ wasn't ALL wrong, there was a reason that templates exist in the first place, and having the entire generics model be just comptime isn't really a decision I agree with. The way I see it, Zig would probably find a niche as a language that configs C/C++ codebase at compile time instead of the C replacement they want it to be.
There are two more languages I have in the Oct repo, SDSL-V for SPIR-V shader/compute kernel authoring and Concept/Vulkan because the 20k line C Vulkan Prometheus runtime for GPU compute that we built is getting kind of unmaintainable even by AI that making up a new programming language to strangler fig refactor it is honestly the least bad option.
ameliaquining 16 hours ago [-]
For what purpose? Different use cases require different language features.
sgt 14 hours ago [-]
Fair enough but people build simple API's with DB interactions in a variety of languages, Go, C#, Java, Zig, Rust, etc.
ffsm8 16 hours ago [-]
I mean I don't have anything against go, but frankly - it's not really better then modern Java.
Each have their trade-offs, both can support native compiled application code. Some architectures are easier to review and code in golang, but others go much better with Javas richer ecosystem and better composability.
zrg 13 hours ago [-]
I've written go most of my career. I've "written" tonnes of AI assisted go. Since February however all my new software projects and production services have been written in rust. I never even wrote rust before December. I've barely even looked at any of the source code, I find i just trust the AI to write rust way more.
But perhaps that's also a side effect of maybe having prior opinions about go and the number of foot guns I've let off
keeda 13 hours ago [-]
I haven't touched Go in over a decade (since before generics!) but I can see why this would be true. My theory is that LLMs absolutely love very tight, focused context. Go inherently restricts how many abstractions you can stuff into your code, and more abstractions tend to make the context a lot more complex and noisy. So LLMs love Go code because it keeps things simple.
The thing about Go, which some have complained bitterly about and others (and TFA) have touted as a strength, is the limited expressiveness of the language (hence my remark about generics!) This is what restricts the number of abstractions in Go code, leading to more verbose but much simpler code all around. Choosing between simplicity and expressiveness is a matter of taste, but also organizational dynamics; for larger organizations which require a large amount of context shared amongst a large pool of employees, it's better for the code to be simpler and locally understandable. As TFA indicates, this has been a guiding principle for Go.
I think what is happening with AI coding is similarly related to context. Consider that while more expressive languages enable more abstractions, they can make the code more concise, but critically, this also spread the logic around. E.g. in large Java codebases you will find deep inheritance hierarchies with class and method definitions spread around a dozen different source files and JavaDoc references.
This necessitates finding and stuffing a lot more information into the context for any given task, a lot of it irrelevant and all of it more complex, because it requires making multiple hops of reasoning to figure out the logic. On the other hand with fewer abstractions, all the necessary code and logic though verbose is right there. It's much easier for a human and an agent to follow that code.
The difference is a human gets tired reading a lot of code, which is what pushes us to devise more abstractions, whereas an AI does not get tired.
I get the sense that if a context is stuffed full of highly relevant information, the agent will perform well regardless of the size of the context window. But the moment you pollute it with noisy irrelevant information, performance will drop regardless of the size of the window. (There are some papers showing this effect IIRC.) Hence simpler code, as encouraged by simpler languages like Go, are more amenable to tighter and simpler contexts, which work better for AI.
hmokiguess 17 hours ago [-]
All I will say is that I agree with how this is framed, it says "an" ideal language. It doesn't say "the" ideal language. Many languages will fit within this scope and concept, Go is not all bad.
throwitaway222 16 hours ago [-]
I have also aligned entirely on Go. Fewest glitches for AI generated code. compile targets are for every platform you need. Very high performance. Doesn't seem to burn tokens as much as other languages.
f311a 16 hours ago [-]
The only problem I have with LLMs in Go is that they also make a lot of concurrency mistakes, in the same way as people. It's easy to fix though, just by asking to double check the code
mg 17 hours ago [-]
My expectation is that AI will give us a way to nicely quantify how productivity is impacted by choice of language. Because we can rerun the same request as often as we like and compare the results.
And I expect that it will turn out Python is the most productive. As it is most easy to reason about. It allows for the most elegant expression of the idea behind a program.
The first tests I have seen seem to confirm this. One recent example:
Purely anecdotal, but my experience has been that LLMs generate low quality python code. It's spaghetti code on par with what I've seen when companies I worked at tried offshoring development. It's basically what you get when you give bad or incomplete specs to a team of inexperienced programmers with poor development practices. It's usually good in small chunks, but it gets extremely sloppy as the scope of work increases and more decisions are introduced. Interestingly, I've seen LLMs generate good clojure code.
My guess is it comes down the the training data more than anything else, although I suspect functional languages will fare a little better. At least that's been my experience. There's undoubtedly a ton of python code in the training corpus and portions of it are of dubious quality. Niche functional languages likely have a smaller training corpus where a larger portion of it is better quality.
williamdclt 16 hours ago [-]
I think it's far from being this simple. What you're describing is productivity on a greenfield project, but what's really interesting is productivity when working on an existing large codebase, with existing conventions, architecture decisions (or lack of)... How easy is it to do a product pivot, to rearchitect for performance, etc etc etc.
Imustaskforhelp 17 hours ago [-]
It is unclear to me though how much of your expectation might be set by the training dataset.
For example, Python and Typescript have the most amount of codebases and training being done on. So I feel as if that plays a part into the overall thing.
Languages which are more niche have genuinely hard times (Try arturo lang for example), so it depends on a lot of things/nuance, or well that has been my experience trying something recently.
My personal opinion is that if each language has the same amount of training. Golang comes close but the first might be Elixir. I have seen Elixir language perform really well with LLM's with magnitudes less training dataset. There have been some studies which had Elixir as the number one language for such tests iirc.
Gleam is a new addition as well and I feel as if it could be good and its another interesting option as well with more type-safety and an interesting language overall.
_virtu 14 hours ago [-]
I've been in elixir for nigh a decade now and the one thing that you can try to pry from my cold dead hands is the BEAM. Elixir and Gleam are my go to languages right now and damn are they fun to write and reason in, but the part that has left me never wanting to leave the ecosystem is BEAM + OTP.
- BEAM makes monoliths sexy. You don't have to worry about a bunch of microservices, just focus on using proper process division for modeling your problem.
- Debugging on the BEAM is first class. Drop into an interactive shell, pull up telemetry, or recon and hammer down on where your live app is slowing down if your metrics have a blindspot.
I could go on and on. I'm constantly blown away every day by the amount of time and effort and all of the sage learnings in distributed computing problems that came out of Ericsson that became the foundation of erlang + OTP + BEAM and in turn elixir + Gleam.
rbjorklin 14 hours ago [-]
Never tried Elixir myself but came here to say the same thing. Tencent put out this study showing that Elixir seems to reign supreme: https://autocodebench.github.io/
devmor 16 hours ago [-]
How do you propose to quantify the terms "elegant" and "easy to reason about"? What unit of measurement do you use for these?
This sounds like your personal feelings, not quantification.
17 hours ago [-]
jopsen 11 hours ago [-]
We're all biased here, me included.
IMO the concurrency model in go is the biggest reason, I'd hesitate to use it.
Managed memory, single threaded with lots of lints and good tooling. Is IMO what can raise my confidence in code, before I even review it.
Granted golang has a really good stdlib. Which counts for a lot.
__MatrixMan__ 16 hours ago [-]
The LLMs will continue to get better at language stuff, better to tell them what to do on the basis of non-language stuff.
Stuff like like which compilation targets are available, or which has the most mature library for what you're doing, or maybe you're integrating with something that anchors you to a specific interface type.
Anchor your language choice to the problem you're trying to solve and the people you're trying to solve it for.
osigurdson 9 hours ago [-]
Learn Go if you have to, or want to learn it. Otherwise, I don't think there is any reason to do so. I agree that it is easy to read, but less so than the language you already know.
Myrmornis 10 hours ago [-]
> By enforcing a single, standardized format via the built-in gofmt tool
I'd read about this many times before I started with Go so I was particularly disappointed to learn that it was a lie.
melodyogonna 16 hours ago [-]
When I use AI with Go I give it this rule:
Prefer standard Go libraries and tools.
80% of the time I can get by without external dependencies (outside of Go's X repository)
sunaookami 16 hours ago [-]
Yeah same but I always allow https://github.com/spf13/pflag because e.g. Claude really struggles with the default flag package (and it's shit in general)
pianopatrick 10 hours ago [-]
Seems to me the ideal language for AI has not been created yet.
unquietcode 10 hours ago [-]
It's hard for me to imagine that the 'ideal' language for AI would even be readable by humans at all. Left to their own devices, these systems seem to make up their own way of communicating ideas.
k__ 16 hours ago [-]
Had the same impression about TypeScript and Rust.
Not as fun to write as Python and Nim, but I don't have to write it.
furyofantares 16 hours ago [-]
I theorized this about a year ago and had a good amount of success vibing small game projects in Go.
I still think Go is a very excellent choice but I have switched to, of all things, AssemblyScript within a Rust host. I've been very happy with it - surprisingly so. Compile time is a major drawback of course.
17 hours ago [-]
WalterGR 15 hours ago [-]
Related, though 5 months is a long time: “A case for Go as the best language for AI agents” (getbruin.com)
The readability is a plus at the same time if I target Rust and build it modular with lots of tests and io pure modules. The review part is not as important if the AI reviews it from various perspectives. With rust I get so much better performance and efficiency.
tsss 2 hours ago [-]
Only in so far that it is the language that I most desperately want to stop reading and writing myself.
kgeist 15 hours ago [-]
I agree with the article, but there's one thing Go has that doesn't help LLMs: structural typing. An LLM has to grep a little more to understand which interfaces a struct implements.
bob1029 17 hours ago [-]
It's definitely more about the ecosystem than the language at this point.
I think the most important thing is how big the standard library is. Pulling in 3rd party dependencies is where I begin to lose a lot of faith with LLM authored code.
dimgl 10 hours ago [-]
I'm currently writing a TUI for a harness I'm building in Go. It's a magical experience, truly.
AnEro 17 hours ago [-]
I hate the rust v go wars, its not x vs y is 'best'. Rather is x better than y and by how much for xyz project done by ABC corp in this era?
As a lead I'd love to use rust, I will put in the time on my own, my team won't or can't. They treat this like any other job they signed up to deliver value with what they know. For hiring not everyone has the talent pool and fund access to get the goat-ed engineers that congregate to tech hubs for maximizing their income. Then if you get through that cherry on top is LLM's are only as smart as you guide it to be. There is probably a staggering amount of ways to write 1 approach to business logic, you may not know the ideal pattern so you'll commit to a worse one on the company dollar.
I'm moving my team's projects slowly to go because, its easy to go from novice to advanced in terms of code writing,legibility and patterns. We also don't have deep ecosystem requirements to ts/python in most of our work. It is verbose but I don't mind that on token spend if it gets done with with validation/error handling which it obnoxiously enforces. It runs cheap, ecosystem is good for platform eng, standard library does a ton out of box.
Dowwie 16 hours ago [-]
Can anyone recommend a strong Go design/development agent skill?
Yeah, I use go and it's great. Most of the time the generated code is good quality also.
If a language is simple, it' easier to generate good code.
patwoz 3 hours ago [-]
Just use rust
frollogaston 14 hours ago [-]
Go was designed as a systems language. They turned it into an applications language too, I'm guessing because turns out the greenthreading was uniquely good for that. But now it's awkward. The pointers and errors are not how you want an app lang to work. And LLMs struggle with error handling even more than humans.
Even as a systems lang, the error syntax is the worst part of Go. Can they at least put the ?/! syntax like in Rust instead of this "if err != nil" spam every other loc?
0x457 15 hours ago [-]
Yeah, no. Its good because LLM likes to copy paste things instead of doing code reuse which is the true go way of doing things. Imo, its hard to review Go code, probably why Go is yet to have a single correct Raft implementation.
I never seen k8s cluster that doesn't have some go process that segfaults once in a while because someone forgot to check `err`.
Only good thing got going for it is its vulnerability scanner. Which will be working overtime with all that "AI-assisted software engineering"
kev009 17 hours ago [-]
This seems like a cope, if you aren't writing the syntax who cares and everything here is even better with a stronger type system like Rust, F#, Scala, TypeScript.
Kuyawa 15 hours ago [-]
99% of my projects are in NodeJS as web apps, so Javascript is king, my coding agents are in Node too, plain, boring, beautiful javascript, not typescript. Yesterday I needed a Rust project and my agents delivered so no need to change from JS
socketcluster 4 hours ago [-]
Yes. Vanilla JS is the best. You don't need TypeScript, Claude never makes type errors. TS just costs additional tokens and fills up the context window with useless type information; the wasted space could have been used to provide additional code/logical context.
baalimago 15 hours ago [-]
Boring is better. Perfection is the enemy of good.
cryo32 14 hours ago [-]
Going to start writing Perl again then.
SPBS 7 hours ago [-]
I'm firmly in the Go camp too but this just reads as unnecessary glazing
> Go solves this through unyielding consistency.
What? Why is the word "unyielding" used here? What was the point of generating this AI article on the google blog post?
fragmede 6 hours ago [-]
No it isn't. The best LLM software engineering language hasn't been invented yet. As a human, spaghetti code sucks and goto's are considered harmful. I can't reason above what my puny human brain can keep in context. Phone numbers are hard to remember, and that's only 7-10 digits. LLMs have no such problems, and as such, should be able to write more performant code given fewer constraints. Given a problem statement, an LLM could "hand" optimize assembly for the specific CPU the code is to run on, eg that exact Intel CPU's speculative decoder pipeline length.
synergy20 16 hours ago [-]
all my LLM coding is in go these days
fpauser 4 hours ago [-]
says google
shevy-java 16 hours ago [-]
In my opinion, the by far biggest problem Go has is called ...
Google.
Now one can say that a programming language and its design or
usefulness is - or should be - decoupled from the company
developing is. I am not opposed to this, in theory, but Google
goes way too much on my nerves these days. And I am hardly the
only one here.
I am not saying this is a rationale used by many other people
either, mind you, but Rust has been taking strides (not that I
am a huge fan of it either but for different reasons) and it
seems to me as if Rust has finally now more momentum than Go,
which I find interesting. Again, this may be a correlation
rather than any causation, but I can not help but notice it.
mbrumlow 17 hours ago [-]
Rust is better. It just is. Go is not bad. But as a long time go advocate, the hurdle for my teams using rust is gone, and thus everything is now rust.
simonw 17 hours ago [-]
Personally I find Rust a lot harder to read than Go.
If you're going to have an agent write most of your code readability is very important.
_verandaguy 17 hours ago [-]
I'll qualify this from my POV (which may be different than GP's).
Go's historic maintainability strong suit has been its simplicity and consistency. The syntax is, relatively speaking, lightweight, the language invites complexity through composition, and information density for any unit of code is typically quite low (which isn't necessarily a bad thing).
In my opinion, though, these are all drawbacks, and Rust addresses all of them. It's syntactically and semantically much heavier, leading to its oft-maligned steep learning curve. It has, uniquely among the major languages, I think, a syntax for expressing variable lifetimes (with its own unintuitive semantics). It stuffs lots of abstraction into a hodgepodge of terse semantics and punctuation.
It sucks to read, until you get really used to it. Then it tends to read really quickly, and, at least for me, it's easier to reason about a conceptually-broad piece of logic if I don't have to jump between different locations in a file, a module, or a package to do it.
With Go, I find it more difficult to get into a flow state, and easier for my eyes to glaze over when looking over large diffs.
It's not lost on me that these are purely subjective arguments, though. My preference remains with Rust, and that goes back to before I used LLMs.
I'm also aware that Go is very prescriptive about how you write it; it's explicitly opinionated, and Rust doesn't have that. It means that most Go code bases will look more alike. I consider this an anti-feature; I believe code should be able to conform to the problem space or product and a good team will find the best way to do that.
orangecat 17 hours ago [-]
Yeah, Go is easy to read in the same sense that English limited to its ten hundred most common words is easy to read (https://xkcd.com/1133/). Whether that nature is helpful or harmful to LLMs is an interesting question.
ndriscoll 16 hours ago [-]
It seems very obviously detrimental to me (in the exact same way it's detrimental to people); e.g. use proper jargon with an LLM and you find it is suddenly an expert. The LLM has no trouble at all perfectly fluently using macros or monads or whatever thing people are afraid of to write simpler, more concise code that directly expresses the business logic in a fully type safe, high performance way that the compiler can introspect for even more information. Go of course lets you do none of those things and can only ever be used for "beginner code" by intentional design.
dralley 17 hours ago [-]
For whatever reason, maybe not even logical ones, Go repulses me. I don't know why exactly, I like the idea of Go, but the aesthetics rub me wrong.
I think it's the use of pointers and "if err != nil {}" error handling spam. It reads as a highly compromised imitation of Python and C rather than a solid execution of some other idea.
Rust is not the most beautiful language out there but it doesn't trigger any such reaction for me. The ? operator and "match", which I use constantly, more than compensate for some of the sigil noise which I barely need to look at much less write most of the time. So Rust wins on that comparison for me.
The "func name() -> retval" syntax also grew on me. I like the fact that Python type annotations copied that approach, and C-style declarations look ugly to me now. Same with C-style /* */ comments.
kev009 17 hours ago [-]
Because Go is kind of a Steampunk design. The creators collectively ignored decades of PL developments. What that nets is kind of a C without sharp edges, but can't be used where C can.
Rust is definitely jarring to look at, in the same way that decoding some strange C declaration can be, in ye olde days when you had to float all this context in your mind while doing work. But with modern tooling who cares: "explain this lifetime to me"
odo1242 16 hours ago [-]
For me it's mainly the if err != nil {} stuff and the fact that everything is package scoped (C-style enums and constants).
You can pretty clearly see the limitations if you read, for example, the type of code the Protobuf compiler generates when trying to compile Protobuf/gRPC enums or structs into the way-more-limited Golang type system (this is despite the two being designed to work together). And it could really do with algerbraic data types and other modern programming language features.
Also the type system does have a couple weird behaviors that seem straight out of JavaScript. Like the difference between struct and interface nil for example:
```
var buf *bytes.Buffer = nil
var out io.Writer = buf // now out is nil
if out != nil {
// This block will execute because out is not nil
out.Write([]byte("crash")) // This line will crash because out is nil
}
```
Many things about the language almost seem to be designed to simplify the implementation of the compiler rather than to benefit the developer experience.
tasn 17 hours ago [-]
It's a matter of expressiveness, Rust expresses more.
E.g. make a table that's 3x3 is easier to read (Go), but the equivalent line in Rust would also include material, angles, height, etc. because the type system encodes much more information.
Though I always found Go to be significantly harder to read than Rust. Sure Rust has some crazy syntax at the edges, but Go makes it very hard to know where imports come from (and thus what they do), and the imperative style + lack of clarity about mutability makes code much harder to reason about.
Buttons840 17 hours ago [-]
Counterpoint: I find Rust easier to read.
mbrumlow 16 hours ago [-]
Might be unpopular, but agents write too much code for humans to read in any meaningful time frame. Using agents to generate code to then require humans to slowly consume it defeats a lot of the speed you gain from AI.
I my self and teams members are slowly reading less code and requiring agents to prove things work the way we want in other ways.
threethirtytwo 17 hours ago [-]
I have an agent read most of the code as well. The agent explains things to me in plain english.
The default sentiment is humans should read code it's more progressive and a leap of faith to start giving that up.
Obviously, I get why you feel humans still reading code is important, but if you look at the progress of AI for the past couple of years, that gap is closing. The trendlines speak of a future where it becomes less and less important.
This was exactly what happened with writing code. Now most people don't write code.
eliasson 17 hours ago [-]
> Now most people don't write code.
I use LLM daily to write code for and "with" me, I also write code without LLM. Most people I come across mix it up. A few do it all by hand, and equally few all by LLM I would say. Is that just in my corner of the world?
threethirtytwo 16 hours ago [-]
The trendlines are moving away from this. It's all happening so fast that not every company is on the same page, but from what I see we are quickly converging on not writing anymore code.
My entire company for example does not write a line of code. We manage agents and that's it. Many, many, many companies and people are already doing this.
throwitaway222 16 hours ago [-]
I have a few utility go codebases that I simply do not read at all - but it's internal tooling so there's literally no point in reading it when the LLM can modify it in seconds to do new things.
simonw 17 hours ago [-]
I don't read all of the code produced by my agents any more, but I like to reserve the ability to do so if I run into a particularly confusing bug, or for any code that's security adjacent.
threethirtytwo 16 hours ago [-]
Same. But usually if I need to read code, I end up telling my agent to summarize it for me.
odo1242 17 hours ago [-]
Personally, Rust or Typescript both happen to be better than Go for me. TypeScript has better type-safety and tooling for user-facing apps, and Rust has better type-safety and tooling for algorithmic stuff or stuff that needs to run fast.
rsyring 17 hours ago [-]
I guess the difference in compile times doesn't matter enough?
ramoz 17 hours ago [-]
idk. In my experience the build/compile experience has been far worse esp for fast iterating. Even concurrency models did not seem as intuitive as Go's. Im no systems expert - have deployed practical and performant distributed systems though.
jhawk28 17 hours ago [-]
Zig seems to have more closely aligned with what Go devs prefer.
jdw64 17 hours ago [-]
Go doesn't have memory safety issues because of its GC, while Zig has UB problems. Zig might have slightly better performance, but I don't think choosing a language without memory safety is a good idea
OutOfHere 14 hours ago [-]
What is UB?
colwont 14 hours ago [-]
undefined behaviour
amazingamazing 17 hours ago [-]
Ignoring performance for the moment (because most situations are bottlenecked on something else), why is rust better?
threethirtytwo 17 hours ago [-]
I agree, but this doesn't justify anything. Saying rust is better because it "just is" won't convince anyone. I'd like to know why you think it's better.
nchmy 17 hours ago [-]
can you elaborate?
greenavocado 17 hours ago [-]
Rust compiler is a tyrant. Type system is strict. Borrow checker is relentless. LLMs can't slop too much without being beaten up by the compiler.
vorticalbox 17 hours ago [-]
True but if the reviewer doesn’t have an intimate understanding of rust then the fact it can’t “slop” is no different than unreadable slop.
Go is simple, no “magic” marcos or meta programming even with just a little programming in any language it’s not hard to understand what the go code is doing.
greenavocado 14 hours ago [-]
That's simply not true. I wrote a piece of software in Rust that is non-trivial, robust, 50k lines of code, and 100% LLM generated, used by four people productively with only one or two minor bugs in the past two man-months
vorticalbox 13 hours ago [-]
question did you review the code or did you test it was working? these are different things. and if you did review it, could an engineer without deep Rust experience have reviewed it just as effectively?
I have no doubt that you can get a LLM to write working bug free code in any language but that is not the topic of the article or my comment.
threethirtytwo 17 hours ago [-]
This is true. I'd like metrics on this though. It could be that LLMs find go easier so they end up writing better code and rarely hitting static errors like a human would in rust. IT could be through scientific measurements that the benefits of static checking could be negligible for LLMs.
No way to know until someone does the science on this. Until then it's just people saying that more static checking is better. But I do think, anecdotally, python is horrible for LLMs.
greenavocado 17 hours ago [-]
Until we can measure slop accurately it's all guesswork
iberator 17 hours ago [-]
except Rust is HARD while GO is super easy.
tibbon 17 hours ago [-]
Rust makes you solve many of your problems upfront, which is a nice feedback loop for using with an LLM. Go does much of this too, but I feel Rust is more experessive and takes the frontloading a bit further.
dralley 17 hours ago [-]
It's not that hard.
17 hours ago [-]
0x20cowboy 16 hours ago [-]
“…requires opinionated simplicity…”
Of course it can’t just be simplicity, it has to be “opinionated” simplicity. Rolls eyes.
summarybot 16 hours ago [-]
lol "Why Go is really good - an article by Google"
bibimsz 11 hours ago [-]
i thought we all landed on Python.
brb, rewriting backend
elzbardico 16 hours ago [-]
Because Go is an absurdly verbose language that hates to the core the idea of expressivity because it prides itself on being dumb.
geertj 15 hours ago [-]
Let me share a hot take. I am deliberately taking this somewhat to the extreme, so please attack the idea not the person. Looking for thoughtful replies and good counterpoints, rather than language zeal.
Let's assume that you need to write a program with a given set of requirements, and that you have a magic wand that can instantiate a high quality implementation of the program in any programming language instantaneously and for free. My hot take is that you would not want to choose Go, and you would likely want to choose Rust.
The Go implementation will have higher memory and CPU consumption due to garbage collection, while still being subject to memory bugs. The Rust implementation would be as efficient as possible on the given hardware with minimum memory/CPU, and it would be immune to memory bugs.
In my view, the biggest challenge with Rust, and where Go wins, is the relative difficulty of writing in Rust as the language is significantly more complex. With LLMs this is becoming a non-issue, and we are getting ever closer to having this magic wand (I'd argue that for smaller programs the wand already exists today). The article advocates that Go has excellent readability. I agree that Go has trivial syntax, but given that it's so verbose, I actually find it easier to read Rust code. Its higher expressivity allows you to see the higher level intention of a piece of code more easily.
Many of the other benefits the article mentions for Go are equally applicable to Rust: compiler error messages are super detailed and a great help to coding agents, auto-formatting, a great language server, and a package ecosystem.
jaynetics 15 hours ago [-]
I agree all in all.
I guess from a pure language POV, one might argue that rust leaves humans with more opportunity to add abstractions that are too clever and too hard to wrap your head around. That doesn't feel like a strong argument, though.
Then there is of course the ecosystem, where go maybe has better libraries for some stuff (while rust may have better ones for other things).
jay_kyburz 14 hours ago [-]
If you are going to take the human out of the loop you could just write the program in assembly or machine code directly.
15 hours ago [-]
TimByte 3 hours ago [-]
[dead]
tizerluo 9 hours ago [-]
[flagged]
ekabod 16 hours ago [-]
[flagged]
efnx 15 hours ago [-]
[flagged]
alexzh3 17 hours ago [-]
[dead]
luciana1u 15 hours ago [-]
[dead]
transdev12 15 hours ago [-]
[dead]
leZon 2 hours ago [-]
[flagged]
purplemoonx 9 hours ago [-]
[dead]
effnorwood 10 hours ago [-]
[dead]
jdw64 17 hours ago [-]
[dead]
FpUser 17 hours ago [-]
Nice try
dude250711 16 hours ago [-]
Google: please don't forget our little language exists :(.
What am I talking about? Nil and partially constructed structs are impossible to prevent the creation of in Go.
Sure, if you’ve got a small program with limited scope, that’s probably fine if you look through squinted eyes. But the teams I work with are working on sprawling, evolving software where the compiler saying “hey, that’s not a valid Widget” would be extremely useful and save much heartache.
An LLM does a good job of “checking” for other uses and “checking” if everything is going to work correctly, but - supposedly we’ve committed the concept to code so that the compiler can actually verify it - and Go intentionally permits invalid states of structs. This makes Go a fundamentally problematic language choice for the kind of software I work with teams on, LLM or not.
But on the other hand, I suppose it makes it a bit more pragmatic - less checks makes for a faster compiler, and fast compilation was/is very high up in the language's requirements and motivation. If you want / need more strictness in your language, there's Rust, Java, C#, etc.
It's sometimes challenging to get a Rust program to compile... but if you do, it's probably going to work.
As for readability, the fact that AI-written Go closely resembles human-written Go is not necessarily a point in Go’s favour.
There's just not many ways of writing Go. It's a very dull language. It was designed to be dull and easily understandable.
if an llm has learned dumb things from dumb users it could disproportionately cause provlems versus other languages, just by being "in a sloppy mood" when writing go.
For me it helped a lot to try to make containerized end-to-end tests and a custom TestMain for this, where I am using podman to run the integration tests. This way the end-to-end tests are forced to be on network level, and you can test protocol and API quirks much easier with LLMs.
Also, never forget to write a bootstrapping docs/ folder so that you don't have to re-explain these things all the time.
In Go the convention is kind of to have a constructor pattern with a NewStruct(...) *Struct method that initializes all properties.
Also can't you build your own validator for that with the reflect package in the Add() method of your UI graph to prevent this sorta thing?
But that doesn't stop you from declaring a var s Struct, and never initializing it, or making a NewStruct {}.
> can't you build your own validator for that with the reflect package in the Add() method of your UI graph
Besides the fact that that would almost certainly significantly hurt performance, how would you be able to differentiate between unitialized data and data that was intentionally set to the zero value?
The go type-system is simply incapable of enforcing nil-safety without being no longer able to compile the go stdlib nor most code in the wild, so it's a quite valid criticism of the go type-system and language, and your comment doesn't hit on a valid solution.
At Netflix, I lead the Go language guild. We've been seen increasing reports of users finding their AI agents writing better Go code than other languages, and increasing reports of projects favouring Go over other languages.
Two additional notes I'll add:
- Go has _great_ resources on writing good Go code, including treasure troves at https://go.dev/doc/effective_go and https://google.github.io/styleguide/go/. edit: Sorry, I forgot to add: we give these resources to AI agents and they use them to produce even better Go code.
- For a language team, Go is a dream. The `go fix` tooling, AST/SSA packages, ease of reading and writing `go.mod` (go mod edit, etc), and various other "platform"-y features make modifying Go code at scale way easier than other languages.
As another example, Go still has not yielded a correct implementation of Raft or Paxos while there are dozens in Java, C++, and Rust. Antithesis found some more bugs in HashiCorp's Raft implementation recently[0]. I'm sure etcd still has some kicking around.
Maybe this is a "don't throw the baby out with the bath water' problem but the general evolution of Go has been lackluster. I reach for Rust, Zig, and modern Java instead depending on the specific needs and constraints.
0 - https://antithesis.com/blog/2026/finding-bugs-in-raft-implem...
Are you saying that this implementation is wrong?
"This Raft library is stable and feature complete. As of 2016, it is the most widely used Raft library in production, serving tens of thousands clusters each day. It powers distributed systems such as etcd, Kubernetes, Docker Swarm, Cloud Foundry Diego, CockroachDB, TiDB, Project Calico, Flannel, Hyperledger and more."
One of the most popular distributed DB is Cockroach which is written in go and also uses Raft: https://github.com/cockroachdb/cockroach/tree/master/pkg/raf...
You may be interested in knowing that the largest managed Kubernetes service in the world (AWS EKS) ripped out etcd for in favor of their homegrown consensus service for large scale EKS clusters: https://aws.amazon.com/blogs/containers/under-the-hood-amazo...
goBGP is arguably even worse.
I don't have a third place in mind that's even worth mentioning relative to these two.
(I have only a rather basic familiarity with go, but was considering gobgp for an infra project...)
[1] https://elegantnetwork.github.io/posts/comparing-open-source...
Gobgp is great if you want to embed it directly into a Go app though. Talos Linux has done that recently.
0: https://etcd.io/blog/2025/autonomus_testing_with_antithesis/
1: https://jepsen.io/analyses/etcd-3.4.3
2: https://github.com/etcd-io/raft/pull/113
Etcd corruption and loss of quorum is extremely common in practice and the GitHub issues sit for years. The design is simple, the performance is modest, yet it still has still never been reliable, despite being marketed as so. I can't speak to whether this is specifically due to their Raft implementation, but I'd argue the entire codebase is over-engineered and questionable.
Its very much {reliable, performant, flexible} pick none.
That the world runs on Kubernetes is no qualitative statement about the correctness of its Raft implementation. You can say that it's clearly good enough to not matter most of the time, but that is a different statement. No matter who you look at, they're just cooking with gas like you do, and they can make mistakes in just the same way.
Now; I'm only attacking your argument. I do neither know nor particularly care about the correctness of that implementation itself. There's been better refutations of the claim you replied to in other answers anyway.
Thats basically it for starters, what non-technical solution do you propose?
I didn't know Go just isn't a good language for it, but now that I know I'm no longer surprised at etcd being problematic.
Sure it may not be the best fit in a scenario where you want a cluster spanned over the entire globe (thats why GKE uses paxos-based Spanner instead of it) , but even spanned across an entire continent (in europe via glass fiber) it works quite well for me. Its one of the least problematic parts of the stack.
> are you saying this implementation is wrong?
> That's not remotely what he's saying at all.
I'm v confused by this thread
That is literally what the comment says.
I hope my every competitor will take your advice to heart, as one of our competitors did when they read that "Go is not a memory safe language", so they wrote a blog about how they are porting to Rust. While our team was moving fast and using those "primitives that should almost never be used" around our long running production code base with success.
Some time has passed and now their company does not exist anymore and we have a lot of their clients.
Thank you!
> Go's internal data structures like interface values, slice headers, hash tables, and string headers are not immune to data races, so type and memory safety can be violated in multithreaded programs that modify shared instances of those types without synchronization.[113][114]
It's close enough for most purposes... but it isn't.
JS is fine for what and where it is, Rust is fine too. I just appreciate the stupid simple nature of Go and it does the job just fine.
If you want to see something that could potentially impact Raft's correctness, search the last couple of days of the HN front page for choreographic languages [1]. But none of these are even remotely mainstream enough to depend on for anything. Nor do I know if anyone in these languages has implemented Raft. A rather good test case for them, if any of them are looking. That's something that could actually help a Raft implementation's correctness, not just fiddle around the edges of local concurrency issues.
[1]: https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
The antithesis author states:
> Go still has not yielded a correct implementation of Raft or Paxos while there are dozens in Java, C++, and Rust.
That says that there are correct (i.e., bug-free) implementations in those languages. The GP noted
> "we’ve found bugs in every Raft implementation we’ve tested, ..."
which says that there aren't any correct ones. You then wrote
> I didn't say other languages don't have buggy Raft/Paxos implementations
which is a strawman. The issue is whether there are correct implementations. That there are buggy ones is irrelevant.
(FWIW I have no dog in this fight ... I'm just reading here.)
>> "we’ve found bugs in every Raft implementation we’ve tested, ..."
> which says that there aren't any correct ones
That only follows if the GP tested every Raft implementation in existence and no new ones were written since.
Edit:
> What are they implying by citing that? That Raft implementations in all languages have bugs?
That's what it says.
> I've already pointed out that is false.
You claimed that, and it's being disputed.
> Please let me know, since you're so comfortable speaking for them.
This has veered into bad faith ... I won't comment further.
> The antithesis author states:
> "we’ve found bugs in every Raft implementation we’ve tested, including HashiCorp Raft, Aeron Cluster, OpenRaft, and MicroRaft"
What are they implying by citing that? That every language has a Raft implementation with bugs? Yes that's probably accurate because lots of people make Raft implementations for fun and learning. Again, Go does not have a single Raft/Paxos implementation that is rock solid. I have seen many in C++, Java, and Rust that are doing tens of millions of requests per second in production for over a decade.
Is their point that Go is not the only language with this problem? My post already points out the track record is that Go is the problem for writing correct code in highly critical domains.
The only way this becomes useful for comparing languages is if somebody gives evidence of correct implementations in other languages. You're claiming they exist but with no evidence and suggesting they're secret. How do you know those don't have bugs? Did any concurrency bug experts do extensive testing on them? And can we disprove secret Go implementations of the same quality?
No, they are citing that every Raft implementation that Antithesis has tested has bugs. The etcd implementation you note in go that has bugs also does tens of millions of QPS and is over a decade old. How are you confident that the proprietary implementations that presumably haven't been fully tested don't have subtle bugs that don't show up in practice?
But good god, the second it gets to anything concurrency-related, it just loses its mind. As much as it's gotten vaguely ok to try to let the agents loose on some bits of the codebase, they simply can't even do table stakes stuff with the kinds of concurrency you see in real life.
Zig is also good at this but requires more up front design (thread-per-core, static allocation, etc.) and consistent checks to verify rules are followed.
It seems like claude code can code Rust pretty well with Opus, and I've started moving codebases away from Golang to Rust at work with Opus. Spin up an LLM and it cranks on it for a while, and as a benefit, I get easy apis to build on with other languages.
And that's the problem with Golang really, not that it's a bad language per se (all languages have footguns), but that the language interoperability story is terrible. Meanwhile Rust and Python/C/C++ go great together like peanut butter and chocolate. And I love it.
And deadlocks. "Fearless concurrency" helps a lot, but logic bugs are still possible.
Java leans heavily in the other direction: a lot of concurrency is added externally, without changing existing code, often in very declarative-flavored ways.
E.g. Future<T> serves as a foundation for a ridiculous amount of stuff, while Go forces channels for `select` whether they model your problem nicely or not, and they're very difficult (often impossible) to wrap without changing semantics.
There are very obviously lots of counter-examples for both langs (`synchronized`, rill in Go, etc), and I expect Go to become more Java-flavored in time (it already has moved this direction somewhat, and 1.27 will enable a lot more). But I think it's a fair summary of broad ecosystem habits.
1: https://tip.golang.org/doc/go1.27 (not yet released)
the source you link to contradicts your own claims.
they say:
> we’ve found bugs in every Raft implementation we’ve tested, including HashiCorp Raft, Aeron Cluster, OpenRaft, and MicroRaft
(besides Go, that's 2 in Java and 1 in Rust)
Go obviously does not stop you from writing buggy code. Neither does rust or zig or whatever. Does go make it more likely to have bugs? Or a specific class of bug? Like, the real world is about trade offs.
Yes, it's a bit of blame the user which will likely get the retort of "but I thought Go was perfect for junior engineers?"
Yes, there are footguns but none of the points therein were compelling.
But Go is also perfectly good at single threaded polling loops.
They used to blame Python a lot too - Python is slow compared to others but not so slow to matter that much, and you can build other services around it to handle certain work.
Facebook - who chose PHP - used to blame iOS/Obj-c as the reason they couldn’t build a decent Facebook native app in the early days (anyone remember Fastbook?)
I would take it with a grain of salt.
A couple more comments like this from you, and I'll be able to say, "cyanmoonx has a history of blaming the talent rather than bad tools". There being a history like that is neither an argument for nor against tools being bad. And also, don't forget that bad tools and bad talent don't rule each other out.
This trend has been there since we started evaluating models using different languages in February 2026 and if anything, the disparity has grown in frontier models. Even Google models prefer Kotlin/C#/Rust for coming up with creative ideas (compilation success is a different story). Data at https://gertlabs.com/rankings
That being said, models love to recommend Go, and Go does have a lot going for it, especially if you are serving a public-facing website. So most of our public facing API handlers are written in Go, and we offload some of our most important binaries to Rust. There are just too many reasons not to use the languages that models think a little more effectively in.
I've found that the LLM generated Go has few mistakes, and generally isn't too obscure. But the volume of code is so high, colleagues do a bad job of reviewing it.
I've seen a lot of very silly decisions made, like returning the wrong HTTP code, or miscategorizing a metric used for an SLO, that I just don't think is helped by the sheer volume of code one has to wade through.
Ironically, we are considering migrating some initiatives to Rust, exactly because experiments indicate it works well with LLM development.
But weirdly Opus (N=1) in Claude Code does okay on it. Enough I can reliably have it write software and feel confident it works.
I agree very strongly. There's no debate about things that have 1000000 permutations in other languages. e.g. The correct format can always be checked by `go fmt` with no real config options. the end.
> ...And so many languages have an opinionated formatter these days
The crux of gp's post is for Go, there is no debate as 'go fmt' is the only one that matters. Black is great, but some people prefer Ruff, leading to ...debates about which formatter the team/org should use. Go's batteries-included philosophy makes those discussions moot on so many levels beyond formatting.
The first one to choose it (whatever it happens to be) wins and that's the end of it. If it isn't the end of it you've got a talent issue.
Guess what other low-level bike-shedding argument 'go fmt' obviates? That's right - tabs vs spaces!
> If it isn't the end of it you've got a talent issue.
I know you meant this as a slur, but the implication is Go works better than other languages for those who have what you call "a talent issue"
In any case, that's a single decision the project lead takes once.
If I do the simplest possible thing that isn't a single word, by highlighting "opinionated formatter these days (e.g. Black)" and clicking search, I get the right result. I also get the right result for black formatter, and I get the right result if I yolo the entire comment as my search.
Similar to black but faster, written in Rust, by the same team who created uv.
> mean this isn't true, formatting is the most trivial part. And so many languages have an opinionated formatter these days (e.g. Black)
I don't think this is correct
[1] https://google.github.io/styleguide/go/
Especially the uv thing. You clone some non-uv git repo that has no pyproject.toml and you don't know what to install. Maybe has requirements.txt but it's partially wrong.
Now they are even better than me.
I do think the way software is organized for primarily agent driven repos will need to change a bit from how I preferred setting things up. (Guessing we're going to be returning to a world of microservices in the near future.)
though the letdown with Java is the wider ecosystem that makes unwarranted contraptions out of simple things.
Thus most JVM implementations had a mix of red (1:1:) and green (M:N) threads, eventually only red threads were kept in the surviving implementations.
With Project Loom now both models are officially supported and part of the specification.
Here from Oracle, as historically taken from Sun documentation for JDK 1.1.
=> Many-to-Many Model (Java on Solaris--Native Threads)
https://docs.oracle.com/cd/E19455-01/806-3461/6jck06gqk/inde...
Yeah Go is my preferred language to code with AI. Second up is type script. Followed by Java, then Python.
One of the cores behind Go is to make language simple, even if at the expense of more verbose code.
Two main examples of this is the infamous 'if err != nil' and how you handle filter/map/funcional operations.
On the other hand, being able to write 'list.filter(v => v.selected)' (or something similar) instead of:
would save much more tokens.https://pkg.go.dev/slices#DeleteFunc
I'm curious to try your proposal, I just want more specifics.
https://github.com/notque/vexjoy-agent/pull/908
I've found a lot of success pointing claude at locally downloaded docs over llms.txt URLs but not sure how to scale the pattern for a bigger project.
After all, learning a new language takes a lot of time. While basic syntax is common and quick to pick up, mastering a language's specific mental model requires a significant time investment, which is why I've used Go before but never seriously.
My interest was piqued recently when I heard about TypeScript tooling being ported to Go, and I know it is incredibly fast. However, where do the results claiming that AI agents generate superior Go code actually come from? Is it a fair, apples-to-apples comparison?
Since Go is a very small language with only 25 keywords, the way you write code is extremely standardized. Because of this, I would assume it naturally produces a lot of excellent best practices and conventions, but I'm not sure if there are actual, direct code examples proving this
I didn't say that. :)
> where do the results claiming that AI agents generate superior Go code actually come from?
Like I said - reports from users.
> Is it a fair, apples-to-apples comparison?
No - these are reports from users, not a systematic analysis.
> I didn't say that. :)
I call this the Go paradox.
I simultaneously believe we should reach for it 80% of the time to solve common collaborative problems. And being a poorer language is actually an asset in these cases.
However, in doing so, we get rusty lose our fluency in more expressive, perhaps even better languages.
How does that work? Are they generating the same project in different languages and comparing the results? What does it mean for the code to be "better"?
It's anecdata and maybe, MAYBE, a spreadsheet. Or a Google Form somewhere.
In my opinion, it has little to do with the speed of the language. The large quantity of source code to train on is quite helpful, but I think it's something else.
There are three things that I think make it well suited to LLM authorship -
1) static typing and a quick compiler - a variable can't change type after it's declared (unlike Python) makes Go more robust compared to dynamic languages. You (almost) always know what the type of a variable is. And the quick compiling with hard-stop errors means that the LLM gets a solid signal for each round.
2) It's quite opinionated, syntactically. There is generally one way that Go lang code is supposed to look. That means it's pretty easy to read as well as write. The lack of things like operator/method overloading make it an easy language to reason about.
3) the stdlib and limited dependencies. Dependency trees tend to be shallow, and because of the static linking (by default), you can generally be confident that what you wrote will run.
If I care about performance, use Rust.
If I care about iteration speed, use TypeScript.
If I want a script or numerical code, use Python.
LLMs are better with Rust because the more expressive type system provides stronger guardrails especially when writing multithreaded code. Go is almost the worst conceivable design of a programming language for LLMs: powerful but weak guardrails. Only C and C++ would be worse.
LLMs don't struggle with the low-level lifetimes like humans do. They struggle with the high-level view because of limited context windows. That's why you want a powerful type system to enforce those global constraints. Go ain't it.
Your other point is even more interesting, e. g. "before AI, Go sucked and nobody used it" - now this may be an exaggeration or simplification, but it is a great observation nonetheless, because Google suddenly tries to connect Go with the rise of AI, almost as if AI could not have risen without Go, which is indeed very strange as an argument to make by Google here. This also reminds me of Google promoting Dart/Flutter before giving up on this and preparing to send it (eventually) to the infamous Google graveyard at some point in the not-so-distant future.
It's also simply poorly informed. Go is a fantastically enjoyable language to program in. In many ways that has been a bit of its curse compared to languages like Rust (which is legitimately a not fun language to write it, and which AI tools are also very good at writing), because keeping the language simple has hobbled some edge cases.
I don't write a lot of Go as my professional life has pushed me more to Rust, but Go and Object Pascal are easily the two most enjoyable languages I've ever developed in.
Javascript takes the throne on that one.
I don't have serious metrics about if Go is better or worse than others, but LLMs seem to do fine with it.
I'm personally leaning into rust for LLM. The whole fussy compiler & errors surface at compile time seems IDEAL for LLMs for me. Hammering compile with tokens is a way better strategy than trying to deduce where stuff may fail at run time and try to catch it via tests.
Tokens are cheap, surprises at runtime are not. So a super anal compiler is what I want. I've looked at lean4 too as the logical next step but not confident I can guide an LLM competently enough for that.
My observation. LLMs find reasoning about Agda as difficult as I find reasoning about C code. I've thrown a lot of gnarly C and Ruby code at all sorts of LLMs and they have only gotten more and more impressive as frontier models have gotten stronger. With Agda, they're like "hmm, tricky" whereas for me it's an impenetrable fortress. I've asked them why they find Agda so much more difficult to write (and why they have to iterate and reiterate many many many times until they get to a destination whereas they can one-shot and two-shot C and Ruby and they tell me its the multiple competing constraints. GLM is hilarious, it flat out refuses to write Agda code but it reads it well enough. They all read it well enough. Fable is obviously great at it. And Opus 4.8/5.0 are great (if they stay on track and don't sneakily go their own way) but they're too annoying to talk to. On balance Kimi K3 is the best balance of not annoying, relatively cheap, and strong -- great model all round tbh.
So yeah, interesting I've discovered the limits of their ability coding-ability-wise. None of them are that good at designing/aesthetic judgment/architecting so thankfully they still need me in the loop.
I did a shoot out of making AI make the same simple desktop app from a SwiftUI reference for 30 different language & desktop framework combinations, and by far the best implementation came from the electron web typescript one. The least amount of LoC, the best and most complete implementation and the fastest to implement.
A bit funny, because I thought... Hmm, so LLM's find Agda natural?
My point being... It's a matter oh habit. After writing C firmware for more than a decade, I can read C easily. I might have to think of some parts and trace the code. But I can grokk it and hold the thing in my head. With Rust on the other hand, I just don't feel it as well. I am afraid writing C gave me brain damage and restricted the lens I can see the world through.
How do you bridge the mental gap?
The gap between me writing high quality rust do this steps and something being logically sound seems enormous to me
Maybe I'm misunderstanding things but I just can't articulate my ideas in casual lean4. But i can do casual rust spec
My advice is to be okay with starting small: don't go for full end-to-end correctness or anything like it. Just think of simple properties you want like 'the list returned by this endpoint should always be sorted in ascending order' or 'this operation should be idempotent' and go from there. Use your favorite LLM to help come up with example specifications from natural language, as a starting point, and try hard to fully understand those.
This kind of work does operate at the frontier of what LLMs can do, so expect to run into roadblocks (wasting tokens proving accidentally hard properties, etc).
LLMs fail to produce bug free concurrent code even for very simple cases.
Golang lacks the ability to build descent abstractions, not even mentioning the wild west of additional tools and libraries needed for non trivial micro services.
For me it is a red flag, that LLMs allow people to produce more bad Golang code faster. This is only optimization for companies which can afford enough software developers to review the excessive amounts of code needed to solve trivial problems in Golang, which are builtin in every descent programming language and/or framework.
Use LMMs and use the right programming language. This might be Golang, but most probably it is C#, Java, Python, Ruby or even PHP. (Or Rust, C, D, ...)
Go's generics are getting a fairly important improvement soon though! Generic methods, finally! It should help open up some more ergonomic patterns: https://tip.golang.org/doc/go1.27
In my experience, LLMs are excellent at finding concurency bugs.
Test it on your last concurrency bug. Point fable at the rough symptoms and ask to find where the issue is by inspection. It'll probably do just fine.
| Go is Readable / Go is Maintainable
It's true that Go, as a low-magic language, tends to be very same-y looking across projects, which is incredible for being able to reliably understand your dependencies' source code. And its tooling is world-class. I love this about Go.
But in practice I've found that, working in a monorepo with multiple teams, contributors that don't have cross-team legibility as a priority will just write SO much more code. And with business logic, often the fact that I can read the code on a line-by-line level doesn't matter if I don't understand the wider context to know how something might effect spooky action at a distance.
Pre-agents, I witnessed a fast transition from a codebase that I could mostly hold in my head to one where large swathes of it had been written and rewritten until they were unrecognizable to me. Now we have agents and, since they are still mostly not good at software engineering in-the-large, the process of knowledge debt accumulation (and ofc tech debt accumulation) in a codebase accelerates tenfold without concerted effort in the other direction. Go being easy to read does not intrinsically help with that.
A simple example is: if you highly value language popularity; Go is not most popular. If you highly value a type system that catches errors; Go's type system catches fewer errors than others. Etc. There is no weighted sum of attributes that will select Go--that's my argument.
- I had to write a moderately complex program. I didn't want to do it in C, and I didn't want to learn Rust.
- So I spent roughly about 2 hours becoming familiar with Go and playing around in Go playground. I decided that this would work.
- And then I got started on my program and I was immediately productive and that software is still running today, along with all the other stuff I've written since then.
Programmer productivity is excellent with Go. And it has a thriving ecosystem. Of course, some things could be better, but I don't really have much issue with it's error handling or types.
I thought this thread was about an ideal language for LLMs, no?
- Better concurrency story
- Native cross-compilation of static binaries (great for CLIs)
- Easier to learn, easier to teach
- Opinionated: You don't have to enforce a single style everywhere
Concurrency died out as an argument when Rust async/await got better. Sure, it has "function colors" and that matters for weird purists who care very much about typing a single "await" in their code, but don't care at all about typing "foo, err := bla(); if err != nil { return err }" all over the place. But it doesn't matter in practice, and tokio has far better concurrency tools: there ares separate channel for mpsc, oneshot, broadcast and watch scenarios, there Streams, JoinSets and a select! macro that can operate more than just channels.
The static compilation argument also died pretty early on when the Rust musl target became more mature. It's still slightly easier to get cross-compilation started with Go, but now that you we have LLMs we wouldn't care.
The learning curve argument is dead. It used to be harder to hire or train Rust programmers and that was a real pain. But LLMs don't care. The same goes for the "Go is built for software engineering" argument, which is a euphemism "Go is our way or the highway level of opinionated". LLMs do not need an opinionated language as much as humans do. If you want all code to follow an arbitrary standard, just ask your LLM to set up one. Engineering teams used to spend years bikeshedding things like brace styles and spaces vs. tabs and Go went ahead stole that opportunity from them. But this is no longer needed.
Sounds like you made a decision right there. The rest is just retro-justification, not a logical argument or comparative between options. It works for you, good.
The only logic that matters most of time is business logic of solution serving problem statement and not logic of choosing a technical stack.
"I didn't feel like choosing $LANG's competitors, so I went with $LANG" might be how languages are chosen for projects in the real world, but it's not exactly a convincing rebuttal to the argument being made.
The choice we made for other reasons is the best one for these constructed reasons that didn't exist until later.
https://en.wikipedia.org/wiki/Choice-supportive_bias
Measuring and Mitigating Post-hoc Rationalization in Reverse Chain-of-Thought Generation https://arxiv.org/abs/2602.14469
I guess if you consider enough attributes or "dimensions" then any programming languages will be the furthest in some direction, including Go.
Listing particular sets of preferences for which Go is not optimal is not sufficient unless you can show the list to be exhaustive.
This isn't an exhaustive proof as no language will every be fully Pareto optimal in practice (it's just not possible, there are too many dimensions), but I'd argue it's at least somewhat close.
One less obvious advantage: Go has greenthreading which is better than JS's async-await. Rust chose async-await to avoid the runtime overhead of greenthreading, but JS has no such reason, it's just a downside.
The tooling will let you do whatever you want, but the lack of standardization is very poor. Even now, many are switching from Eslint to Oxlint. Or Jest to Vitest. Or tsc to faster build tools. There is massive fragmentation.
I frankly yearn for a language that is always backwards compatible (JS itself might be, but ESM/CJS/etc. won’t be because the language relied on 3rd party/runtime-provided methods of importing modules for so long…), and actually has standard basic tooling from the start. Along with halfway decent security posture towards dependencies. And no need to manage a runtime. And produces smaller images.
Like if it’s just about the language, sure TS is extremely usable, async is extremely easy because it’s not a real thread, etc etc. But has plenty of quirks due to being tacked on top of JavaScript. (For example, being forced to import typescript from “.js” extension and not “.ts” with certain normal compiler settings…)
That's the main selling point, with a secondary point that it statically compiles so you don't have to do a whole Python/JS distribution thing for CLIs.
Java feels like the closest contender here, although it really sucks for CLIs due to start up times. I don't think it's the easiest to learn either, but I've never tried all that hard.
It only really makes sense to me at org-scale, though. I think you raise a very good point for individual projects, I too normally don't choose Go for that (unless I need compilation to make distribution to myself easier on corporate laptops).
Can you imagine if structural engineers rushed to post comments about how they decided to use wood for all their projects because it was simple to get up and running with, and they didn't want to have to deal with the all complexities of having to learn about metals like steel?
There’s no equivalent competitor, it’s the best if u want to just write lots of undifferentiated code.
To caveat this if u want to run about 50 agents or so in parallel, all the typescript projects burn ur disk via node modules. The rust ones take forever to compile and burn too much compute
Go can.
There’s no equivalent competitor, it’s the best if u want to just write lots of undifferentiated code.
Go is similar to popular languages like C, JS/TS, & Python. And so, easy to get started.
> highly value a type system that catches errors
Probably these folks already use even less popular ML-style languages like OCaml & Haskell; or (comparatively) obscure ones like Agda, Idris, & rocq/Coq.
Having said that: my opinion is that LLMs thrive by working in a tight loop. Unlike a human, they thrive with more and tighter constraints (and the better models are obviously far better in this regard).
I want to ditch the things that made writing code easier due to the limitations of humans, and embrace something that an LLM can leverage for better results. For me that means: an especially rich type system, (ideally pure) functional code, efficient systems-level performance and leanness. Good error messages that guide the LLM incrementally.
Go does not provide much in the way of those 3 desires, so calling it "ideal" with nothing aside from anecdotes to back that up is not compelling.
1. JS is mem-safe, single-threaded, and there are lots of training data. Easily my first choice. I'd put Python here as well, although I don't like it personally. Both should be used with "avoid external deps" in your AGENTS.md
2. Go might be a good second choice. Simple language, IMO good primitives for concurrency, well-designed std, therefore smaller potential for supply chain attacks.
3. Elixir/Erlang, little training data but rising. Safe language, safe concurrency, immutable, scalable, there are some many advantages... It has been avoided because it's different but that could change drastically in the age of LLMs.
4. Rust is probably next choice, along with C++, because while Rust is safer, the language is quite complex. C might be here too, there is a lot of training data, but every project is different and the language is very unsafe.
5. Zig, I really like the language, but it is terrible for LLMs, mainly because it's constantly changing, and the std is also under-featured and IMO weirdly designed. It's a fun language for hobby hacking, which I believe is not going anywhere, it's just not going to be something you will be payed for.
At work, we use C#. I'm shocked at how much worse it is. I've also used a bunch of Python, but I still feel the quality isn't as good as the codebase grows, but I didnt put as much effort trying to improve it.
Is Go better than CSS if you are doing web layouts? Is it better than zig if you are outputting minimal wasm deliverables? Is it better than swift if you are doing iOS specific development? Is it better than bash for OS scripting?
Think about what you are doing and choose appropriately. This was true before LLMs.
Are you having fun? Chose LISP then
The article specifically discusses how Go is well-suited for LLMs. It's not going on about general programming topics.
what would be the purpose then?
Token use didn't seem to be a criteria from my casual reading, but maybe you can illuminate me what section pointed to that, I may have been too superficial in my reading
It's hard not to, given your comments in this thread.
Which tradeoffs are you willing to accept? Zig (along with several other languages) is superior in a lot of ways for that type of job, but I still settled on Go for a particular minimal WASM (browser) project. It wasn't my first choice, but it was where I ended up because LLMs kept going out to lunch in other languages and I didn't have anywhere close to the required budget to write it by hand. I read some comments like these about Go in the past so the Go attempt was mostly a contrarian Hail Mary after so many previous failed attempts in more technically well suited languages and... it worked! Shockingly well.
It still isn't my first choice for it, but having something useful with happy users beats technical imperfection every day of the week as far as my needs go. Go really did show its worth as an LLM target for that particular workload. Whether or not that is reproducible for any other project remains to be seen, but there seems to be a growing sentiment that echos the same. There just might be something to it.
There are language implementations that would have been more minimal than that, sure, but there was no obvious way to get LLMs into alignment. I tried. Multiple times. When I switched to Go, it just worked. It may not be technical perfection, but it let me ship something I had almost given up on and it has satisfied users. The tradeoff was worthwhile for my needs. That tradeoff may not be acceptable in all cases. Hence what is best being meaningless without at least defining which tradeoffs you are willing to accept.
Two things to keep in mind here:
1. TinyGo is not Go, more Go-like or adjacent
2. 10KB still matters a lot in a lot of minimal target/usage scenarios
Exactly. Go is a language. Tinygo is an implementation, like gccgo, gc, llgo, etc. Just as gcc, clang, and msvc are not C.
> more Go-like or adjacent
It is true that recover isn't fully spec complaint at this time. That's not entirely unusual for an implementation, though. msvc is famously not 100% spec complaint with C, but Microsoft still officially considers it a C compiler, as do most who use it to compile their C code. There is usually a little grace given.
It is not like Solod that is Go-like but trying to do something quite different. Tinygo is intended to be a proper Go compiler implementation and has achieved that, aside from the recover situation.
> 10KB still matters a lot in a lot of minimal target/usage scenarios
But, of course, if the LLM cannot wrangle the language then it doesn't matter. Nobody cares how large or small your program is if you never ship it. That only matters if you are using LLMs, but since that's what we have always been talking about...
Go is behind, specifically, you have no guarantees that a given machine has Go installed, and doing stuff like gluing commands together, inspecting some files, pipe output around, or automate the boring thing in 30 seconds.
Sure Go beats bash or sh when the thing you are doing starts to become real software, but that is a problem that sits between the chair and the keyboard.
People who want to use the most appropriate tool.
> Use the ones more appropriate for what you are trying to do.
What they are trying to do is find a programming language that LLMs work well with.
> So you are using Go with LLMs for the objective and destination of token consumption for token consumption sake?
The trolling gets more intense with each comment ...
P.S. Someone else responded:
> But this isn't a user story. The user story is what you should be picking the tool for.
I don't see how this is at all relevant to my comments. I'm certainly not going to argue about what some other party should or should not be doing.
But this isn't a user story. The user story is what you should be picking the tool for.
I’ve had a great time doing LLM assisted coding in Zig, and it seems comparable to the generic Typescript/React I do at work.
I don’t doubt simplicity and good PL design pay dividends, but everyone’s favorite language can’t be the silver bullet in our new LLM world. Things just don’t add up, and I keep seeing it for Erlang, Gleam, Lisp, C, Rust, Go, TypeScript, Python, etc.
And to pick on Go a little bit, I don’t think it has any unique qualities that make it better for LLMs, where I think you could make that argument for other modern languages that offer new features leveraging their compilers and enforcing more correctness guarantees.
It would be neat to see a matrix of compile times vs. language features, showing things like:
- Bounds checks
- UAF prevention
- exhaustive enums
- test speed
But I think even among those the subtleties would make a fair comparison impossible.
Anyway I think this is all very nuanced, and anyone proclaiming language X is the language to use in 2026 lacks the experience/knowledge to consider these trade-offs and can safely be ignored.
The counter argument here is that these checks cause slower compile times and were designed to prevent common mistakes humans make.
If models get good, they may not need the same checks human written code needs. For example, frontier models already will virtually never produce a typo.
Humans need time to think, but a model’s bottleneck is in how quickly it can verify its work. Slower compile times hurt a models ability to iterate.
I don’t think we’re there yet (and we may not get there). But there is an argument to be made that languages with faster compile times may be better for LLMs in the long run than languages with strong checks but slow compilation.
"After 7 years in production, Scarf has reluctantly moved away from Haskell"
And moved to Python, pretty much for the reasons you stated
I was curious about this so I dug further, and by the author's own admission, they've only made the switch for basic CRUD logic without performance needs, not their core services: https://news.ycombinator.com/item?id=48865986.
It's also pretty unsurprising, given what we know about LLMs' style transfer abilities, that transferring parts of an existing Haskell codebase into Python would avoid a lot of the errors and pitfalls that codebases originating in Python are known for. From my experience writing lots of Python, this does not continue to hold true as you let the agents loose on your Python codebase.
~ Oreo cookie company.
(Someone who doesn't even eat cookie but heard a lot of praise of Oreo)
- There's a lot of Go code out there which the models have seen, so they know how to write it.
- Go has an exceptional standard library, so you don't need to drag in 100 dependencies to create a simple web app.
- Go compiles extremely quickly for incremental builds, which really matters when agents are building and running tests constantly.
- Go has a goldilocks blend of performance and safety. You get a good type system and excellent runtime performance without forcing the model to spend cycles fixing Rust lifetimes or Swift concurrency issues for a marginal incremental gain.
- Go is relatively stable, so the LLM's memorized knowledge is still pretty fresh (as opposed to something like SwiftUI, where the API changes rapidly).
- LLMs have clearly been trained on a lot of Rust as well
- Compile times are counterbalanced by strong compiler with excellent error messages, and "cargo check" can catch many issues without a full build.
- If you're willing to accept Go levels of performance from Rust, there's nothing preventing you from using copies and clones rather than borrows, which makes most code dead simple.
- For most major dependency types, there exists a clear "winner" in terms of community adoption, so the fact that it's not in the stdlib is not that problematic.
With that said, I have not done an extensive amount of agentic development in Rust, so maybe I just don't have the reps to compare fairly.
Nothing costs more tokens than an LLM trying to debug errors caused at runtime which doesn't map well to it's "intelligence" compared to what Rust provides
With golang, all borrow checker problems go away. This is a good trade off if your app is not cpu-bound, which most are not. If you need every last drop of performance then rust is a better choice of course.
However, I have run into a few cases of runtime null crashes in go.
You only have to compile when you actually want to test the behavior, which tends to be right on the first try more often as a result of the strict compiler.
Rust or Nim are really the ideal targets for LLMs and will continue to grow. As LLMs write more code and as humans review less, it will be more important to have confidence that your code doesn't run into a weird one off runtime heisenbug issue.
My background is in data science and MLOps, where Python rules. But the focus is now less on building new AI models, and more on building the infrastructure and API calls with AI Agents. Go has a great async model, stellar performance, amazing tooling ecosystem, and far less ways of doing things than Python.
I except grow to become more and more popular, as our LLMs are now writing most of our code. Between a 50 MB portable binary in Go with 10x performance, and a 5 GB venv in Python with lack of proper parallelism, the choice is easy.
I'd read about this many times before I started with Go so I was particularly disappointed to learn that it was a lie. The most important task of a code formatter is to break long lines; it doesn't do it. It doesn't even have an option to do it!
https://github.com/SteveCastle/loki
That being said, the whole thing about go being "readable" is a little bit of a two-edged sword. Sure, it's straight-forward to read, but it's pretty verbose. And agents are good at producing a lot of text. The problem with reviewing go code for me is to see the forest for the trees. Subtle misunderstandings often hide in the vast amount of code that you have to read through while keeping the whole context in your head.
Anyway, it turned out that Go ironically makes it difficult to collect per-test-case coverage data. In spite of the standardized tooling it looks impossible to write a standardized collector that would run on most codebases. In hindsight using another language would have been a better choice
I think partly it's because the training set contains a lot of JS, but also because complex software written in JavaScript must have impeccable architecture in order to exist at all.
It's rare to encounter a complex, functioning JavaScript application with bad architecture. I've never met any engineer smart enough to maintain a large spaghetti-code JavaScript project.
On the other hand, I've seen horrible TypeScript projects. If it wasn't for the helpful type annotations, no human being would have been able to maintain it.
Joking aside, as much as Go's stdlib and tools do the heavy lifting here, Go's verbostiy and expressing simple things in lots of lines worked against me most of the time.
Maybe my problem is I'm using a language with exceptions, so trying to go against the statistical grain, with return values, is just too much.
Also, Go makes it way too easy to accidentally swallow an error. Rust doesn't have that problem.
Tencent put out this study showing that Elixir seems to reign supreme: https://autocodebench.github.io/
These have been my and friends' observations since LLM-assisted coding started picking up steam. Go's simplicity, consistency, stdlib and tooling seem to make it very reliable for LLM generation, and it was especially true during late 2025 / earlier this year when frontier models weren't as strong; might not be as noticeable now.
As a long term C programmer and start using go from the early days, really love it's rich ecosystem and portability.
Nowadays, for any backend code, i just let agent to write using go, and for resource constraint environment, i just use rust.
And both have good C interop, and good ffi interface to hook into more higher level language such as Swift/Kotlin if one wnat to develop some mobile Apps
forbidigo is what allows me to keep ambient config out of my app, and restrict file access to a small set of paths. The coverage tool has "nocover", so you can guarantee that every realistic path is exercised at least once ("100%" code coverage, which is not a marker for testing completeness, but rather for flagging code you forgot to test). Linting is really good as well.
The only thing I haven't found is something to enforce error handling. Rust is better for error paths because you're not allowed to ignore them.
Maybe we are using different tools (or we've set it up wrong) but I'm consistently surprised at how slow Go's linting is (using golangci-lint). Takes nearly 5 minutes on our codebase after any change (which means I just don't run it locally or in-editor). It's remarkable how poor the experience is after using tools like Python's Ruff (instant) or Rust's Clippy. I'd have expected a fast, default setup that I could tune.
Event JS's Eslint, which runs in actual JS, takes 21 seconds for a full sweep (which I don't normally run, since the in-editor hints are so fast)
It's surprising, because so many of Go's dev tools are so well thought out!
errcheck, generally as manifested in golangci-lint, ensures you can't forget to do something with them. It would be odd for you to know about forbidigo but not errcheck as the former is much less widely known; is there something that errcheck doesn't do for you?
It's worth pointing out that "discard this error on purpose" is a legitimate form of error handling, so "enforce error handling" can't really constitute banning that. That's not a Go statement, that's just true in general... it is sometimes valid to just ignore the error, because there's nothing useful to do with it anyhow. I would agree the ignoring should be explicit, but it is an option.
https://github.com/kstenerud/yoloai/blob/main/docs/contribut...
Poor defaults break systems by a thousand cuts. They seem to make sense when designing the language (more convenient, less typing, etc), but then they very quickly become liabilities as project complexity increases. Go made the mistakes of mutable-by-default and silent-error-dropping, but their cyclical-import-forbidding was a good call.
https://webassembly.github.io/spec/core/text/index.html
> Gophers often speak of how they love that they can never tell who on their team wrote a particular piece of code—it all looks the same.
Multiple languages can have a degree of understabillity, but what matters most is context, because sometimes we need to code in a way to solve a specific problem like performance and it should be kept as is.
Another side subject I should add is about test coverage, although code is cheap, mainly because AI, guarantee that new changes to a stable code should continue to work as expected.
I worked on a few go projects with bad structure and some of them with really low test coverage (e.g. 8%), so part of the post resonates with me about we as software engineers should pursuit good architecture and other skills to allow long term maintenance.
Might be a skill issue, but I got frustrated with it on new projects constantly.
Also, I tend to ask planning questions, like "how would you implement this" and "what would the API changes be?" I'm picky about API's. Lately I've been using Deno workspaces (multi-package repos) and tell it when to make a new package or a new entrypoint. Maybe that helps?
If I just ask for features and don't look at the code, it will definitely make a mess, though. (A working mess, but it takes a while to refactor my way out.)
That's not really a typescript thing though, just an LLM thing.
Pichai wants to eliminate engineers, and DeepMind wasn't fast enough or too noble for it. Now people need to be propagandized for their obsolescence.
Poor correctness guarantees, especially w.r.t concurrency. Nil pointer. Why.
LLMs are like a magnifying function. Whatever you put in you get back 10x over.
In the case of Go, in goes verbosity, Nil pointers, poor concurrency and synchronisation primitives (or poor performance of the safe ones, leading to sync.Mutex everywhere anyway). Also Go prioritises local readability over global understandability which is a poor tradeoff for LLMs with limited context windows.
So the LLM generates absolutely monstrously huge amounts of very hard to review very likely incorrect code.
No thanks.
Rust > Go.
In goes powerful, terse type system. Strong correctness guarantees not just around memory and pointers but also data races. A tendency towards using the type system to model invariants instead of relying on procedural guards and runtime assertions etc. Producing denser code is an LLM feature, it increases context window efficiency. Similarily the typesystem takes something that the LLM can spend a bunch of thinking tokens on to create a powerful global constraint. This fixes the global reasoning/context problem by pushing it back onto the typesystem.
Depending on the quality of your robot you will get different quality of code out but the ceiling is much higher. With Go better robots don't help much, even the highest quality robots output insanely verbose Go. Sort of just like with people... sort of like the language was designed as a lowest common denominator tool...
For a seasoned Rust programmer the output probably won't be hard to review, it will be easy to look at the types and either say "yeah that should probably be correct" or "no robot, do better".
You simply can't actually review the output of the slop cannons with Go, there is too much, looking at a struct tells you almost nothing about how correct the thing likely is, etc. The tests don't help either because there is going to be 10x the usual amount of those too so trying to review those for correctness is the same Sisyphean endeavour.
The biggest barrier to Go adoption seems to be Google's internal resistance to migrate C++/Java code bases to Go and refusal to admit that Go is an amazing application programming language and not really a systems programming language for bare metal OS/driver work. For example, one of the biggest barriers to Fuchsia adoption has been Google asking people to commit to Dart, I think Fuchsia would have fared a lot better as an Android successor/alternative if the official applications programming language just been Go.
(BTW Carbon isn't even a real programming language, it's still somehow stuck at 0.0.0.0 after 4 years of development which is honestly insane.)
Oh, so, little bit of self-promotion: if you like Go but is frustrated with the ergonomics of it, I would ask you to try out the programming language I developed, Oct, for LLM coding which you can kinda think of as my attempt at making Kotlin for Go's Java: It uses a codegen compiler and compiles to a plain Go binary, so it runs on everything that Go runs, and there is a lot of extra features as well: Rust style exhaustive tagged/payload enums/`match`, C#'s immutable records updated with `with`, exhaustive error handling easy parallel concurrency, xUnit.NET style unit test harness, TypeScript style compile time constraints, F# like SI unit system, Go code generation metaprogramming, etc. Would love to have some Go experts here on HN take a gander at it and provide some feedback.
https://github.com/yuechen-li-dev/oct
I have found exactly the opposite to be true: as always, people think they can write safe concurrent code without the machine checking them and end up getting it completely wrong in lots of subtle cases. Except the problem is now much worse because you're not even writing the code, or in many cases, reading it. I prefer a language with a type system that saves me from the review burden of closely checking (and pretty much always finding issues in) concurrency invariants. And even tells me a bit more beyond that about what the code is intended to do.
That's a pile of bollocks, pardon my French. Source/proof?
And to the contrary:
I've been working on a TS codebase that calls into C++ native/wasm-compiled code for six months now. The code is mostly LLM written.
Over these last six months we had four use-after-free and two other ownership-related bugs in LLM-generated TS code.
Whereas we had zero issues of any such kind with LLM-generated Rust code that sits in another two native/wasm-compiled metacrates we use.
LLMs are not much better at ownership tracking than humans.
Especially if resource acquisition and release are far apart in code and/or somehow nested/stacked/non-straightforward.
If there is a problem with global lifetimes then the problem is certainly the person driving (or not) the LLM. Global lifetimes? FFS. Rust is hard because writing services that don’t have bugs is hard.
LLMs are not currently able to vibe a sophisticated application or service in rust. If it tells you it can do it in typescript or python, the it most likely certainly has not and you will have a wonderful time in production. Rust will burst that bubble.
And as other commenters here have said, Rust's main issue for LLMs is infectious lifetime propagation, where the borrow checker knows you violated a lifetime constraint but doesn't tell you how to actually solve it, so LLMs get error messages like:
And instead of trying to reason through the ownership graph, they just take the shortest path to get these things to go away by bypassing the borrow checker entirely, which defeats the entire point of using Rust to begin with.If the premise of the article is true, and I think that it is, that's quite the downside for AI coding with go. The premise being that reviewing now plays much more of a role than writing.
Personally, I'd rather review, say, a ruby oneliner that extracts specific row values from a csv file with filter_map, compared to 40 or so lines of go, many of which I'd have to check individually for possible mistakes.
IIUC Fuchsia uses Dart mostly for UI stuff and Go has never really tried to be competitive there? I don't see much of a reason to suppose this is a serious bottleneck to Fuchsia adoption, as opposed to the obvious reasons why it's hard to displace an existing OS with a huge install base.
Citation absolutely needed.
I think boilerplate & verbosity is an even bigger drawback with LLMs than human coding since context rot and "Lost in the Middle" phenomenon has so much effect on code quality
It seems that LLMs benefit from semantic and syntactical density
I have some very heavy criticism for Zig technically, because their whole thing about "no hidden control flow" becomes "shove all the hidden control flow into a second hard to debug runtime that runs at compile time", and manual allocation for everything is incredibly tedious and hard to keep track of in production code. I mean, C++ wasn't ALL wrong, there was a reason that templates exist in the first place, and having the entire generics model be just comptime isn't really a decision I agree with. The way I see it, Zig would probably find a niche as a language that configs C/C++ codebase at compile time instead of the C replacement they want it to be.
There are two more languages I have in the Oct repo, SDSL-V for SPIR-V shader/compute kernel authoring and Concept/Vulkan because the 20k line C Vulkan Prometheus runtime for GPU compute that we built is getting kind of unmaintainable even by AI that making up a new programming language to strangler fig refactor it is honestly the least bad option.
Each have their trade-offs, both can support native compiled application code. Some architectures are easier to review and code in golang, but others go much better with Javas richer ecosystem and better composability.
But perhaps that's also a side effect of maybe having prior opinions about go and the number of foot guns I've let off
The thing about Go, which some have complained bitterly about and others (and TFA) have touted as a strength, is the limited expressiveness of the language (hence my remark about generics!) This is what restricts the number of abstractions in Go code, leading to more verbose but much simpler code all around. Choosing between simplicity and expressiveness is a matter of taste, but also organizational dynamics; for larger organizations which require a large amount of context shared amongst a large pool of employees, it's better for the code to be simpler and locally understandable. As TFA indicates, this has been a guiding principle for Go.
I think what is happening with AI coding is similarly related to context. Consider that while more expressive languages enable more abstractions, they can make the code more concise, but critically, this also spread the logic around. E.g. in large Java codebases you will find deep inheritance hierarchies with class and method definitions spread around a dozen different source files and JavaDoc references.
This necessitates finding and stuffing a lot more information into the context for any given task, a lot of it irrelevant and all of it more complex, because it requires making multiple hops of reasoning to figure out the logic. On the other hand with fewer abstractions, all the necessary code and logic though verbose is right there. It's much easier for a human and an agent to follow that code.
The difference is a human gets tired reading a lot of code, which is what pushes us to devise more abstractions, whereas an AI does not get tired.
I get the sense that if a context is stuffed full of highly relevant information, the agent will perform well regardless of the size of the context window. But the moment you pollute it with noisy irrelevant information, performance will drop regardless of the size of the window. (There are some papers showing this effect IIRC.) Hence simpler code, as encouraged by simpler languages like Go, are more amenable to tighter and simpler contexts, which work better for AI.
And I expect that it will turn out Python is the most productive. As it is most easy to reason about. It allows for the most elegant expression of the idea behind a program.
The first tests I have seen seem to confirm this. One recent example:
https://danluu.com/pl-tokens/
My guess is it comes down the the training data more than anything else, although I suspect functional languages will fare a little better. At least that's been my experience. There's undoubtedly a ton of python code in the training corpus and portions of it are of dubious quality. Niche functional languages likely have a smaller training corpus where a larger portion of it is better quality.
For example, Python and Typescript have the most amount of codebases and training being done on. So I feel as if that plays a part into the overall thing.
Languages which are more niche have genuinely hard times (Try arturo lang for example), so it depends on a lot of things/nuance, or well that has been my experience trying something recently.
My personal opinion is that if each language has the same amount of training. Golang comes close but the first might be Elixir. I have seen Elixir language perform really well with LLM's with magnitudes less training dataset. There have been some studies which had Elixir as the number one language for such tests iirc.
Gleam is a new addition as well and I feel as if it could be good and its another interesting option as well with more type-safety and an interesting language overall.
- BEAM makes monoliths sexy. You don't have to worry about a bunch of microservices, just focus on using proper process division for modeling your problem. - Debugging on the BEAM is first class. Drop into an interactive shell, pull up telemetry, or recon and hammer down on where your live app is slowing down if your metrics have a blindspot.
I could go on and on. I'm constantly blown away every day by the amount of time and effort and all of the sage learnings in distributed computing problems that came out of Ericsson that became the foundation of erlang + OTP + BEAM and in turn elixir + Gleam.
This sounds like your personal feelings, not quantification.
IMO the concurrency model in go is the biggest reason, I'd hesitate to use it.
Managed memory, single threaded with lots of lints and good tooling. Is IMO what can raise my confidence in code, before I even review it.
Granted golang has a really good stdlib. Which counts for a lot.
Stuff like like which compilation targets are available, or which has the most mature library for what you're doing, or maybe you're integrating with something that anchors you to a specific interface type.
Anchor your language choice to the problem you're trying to solve and the people you're trying to solve it for.
I'd read about this many times before I started with Go so I was particularly disappointed to learn that it was a lie.
Prefer standard Go libraries and tools.
80% of the time I can get by without external dependencies (outside of Go's X repository)
Not as fun to write as Python and Nim, but I don't have to write it.
I still think Go is a very excellent choice but I have switched to, of all things, AssemblyScript within a Rust host. I've been very happy with it - surprisingly so. Compile time is a major drawback of course.
https://news.ycombinator.com/item?id=47222270
203 points | 5 months ago | 304 comments
I think the most important thing is how big the standard library is. Pulling in 3rd party dependencies is where I begin to lose a lot of faith with LLM authored code.
As a lead I'd love to use rust, I will put in the time on my own, my team won't or can't. They treat this like any other job they signed up to deliver value with what they know. For hiring not everyone has the talent pool and fund access to get the goat-ed engineers that congregate to tech hubs for maximizing their income. Then if you get through that cherry on top is LLM's are only as smart as you guide it to be. There is probably a staggering amount of ways to write 1 approach to business logic, you may not know the ideal pattern so you'll commit to a worse one on the company dollar.
I'm moving my team's projects slowly to go because, its easy to go from novice to advanced in terms of code writing,legibility and patterns. We also don't have deep ecosystem requirements to ts/python in most of our work. It is verbose but I don't mind that on token spend if it gets done with with validation/error handling which it obnoxiously enforces. It runs cheap, ecosystem is good for platform eng, standard library does a ton out of box.
If a language is simple, it' easier to generate good code.
Even as a systems lang, the error syntax is the worst part of Go. Can they at least put the ?/! syntax like in Rust instead of this "if err != nil" spam every other loc?
I never seen k8s cluster that doesn't have some go process that segfaults once in a while because someone forgot to check `err`.
Only good thing got going for it is its vulnerability scanner. Which will be working overtime with all that "AI-assisted software engineering"
> Go solves this through unyielding consistency.
What? Why is the word "unyielding" used here? What was the point of generating this AI article on the google blog post?
Google.
Now one can say that a programming language and its design or usefulness is - or should be - decoupled from the company developing is. I am not opposed to this, in theory, but Google goes way too much on my nerves these days. And I am hardly the only one here.
I am not saying this is a rationale used by many other people either, mind you, but Rust has been taking strides (not that I am a huge fan of it either but for different reasons) and it seems to me as if Rust has finally now more momentum than Go, which I find interesting. Again, this may be a correlation rather than any causation, but I can not help but notice it.
If you're going to have an agent write most of your code readability is very important.
Go's historic maintainability strong suit has been its simplicity and consistency. The syntax is, relatively speaking, lightweight, the language invites complexity through composition, and information density for any unit of code is typically quite low (which isn't necessarily a bad thing).
In my opinion, though, these are all drawbacks, and Rust addresses all of them. It's syntactically and semantically much heavier, leading to its oft-maligned steep learning curve. It has, uniquely among the major languages, I think, a syntax for expressing variable lifetimes (with its own unintuitive semantics). It stuffs lots of abstraction into a hodgepodge of terse semantics and punctuation.
It sucks to read, until you get really used to it. Then it tends to read really quickly, and, at least for me, it's easier to reason about a conceptually-broad piece of logic if I don't have to jump between different locations in a file, a module, or a package to do it.
With Go, I find it more difficult to get into a flow state, and easier for my eyes to glaze over when looking over large diffs.
It's not lost on me that these are purely subjective arguments, though. My preference remains with Rust, and that goes back to before I used LLMs.
I'm also aware that Go is very prescriptive about how you write it; it's explicitly opinionated, and Rust doesn't have that. It means that most Go code bases will look more alike. I consider this an anti-feature; I believe code should be able to conform to the problem space or product and a good team will find the best way to do that.
I think it's the use of pointers and "if err != nil {}" error handling spam. It reads as a highly compromised imitation of Python and C rather than a solid execution of some other idea.
Rust is not the most beautiful language out there but it doesn't trigger any such reaction for me. The ? operator and "match", which I use constantly, more than compensate for some of the sigil noise which I barely need to look at much less write most of the time. So Rust wins on that comparison for me.
The "func name() -> retval" syntax also grew on me. I like the fact that Python type annotations copied that approach, and C-style declarations look ugly to me now. Same with C-style /* */ comments.
Rust is definitely jarring to look at, in the same way that decoding some strange C declaration can be, in ye olde days when you had to float all this context in your mind while doing work. But with modern tooling who cares: "explain this lifetime to me"
You can pretty clearly see the limitations if you read, for example, the type of code the Protobuf compiler generates when trying to compile Protobuf/gRPC enums or structs into the way-more-limited Golang type system (this is despite the two being designed to work together). And it could really do with algerbraic data types and other modern programming language features.
Also the type system does have a couple weird behaviors that seem straight out of JavaScript. Like the difference between struct and interface nil for example:
```
var buf *bytes.Buffer = nil
var out io.Writer = buf // now out is nil
if out != nil {
}```
Many things about the language almost seem to be designed to simplify the implementation of the compiler rather than to benefit the developer experience.
E.g. make a table that's 3x3 is easier to read (Go), but the equivalent line in Rust would also include material, angles, height, etc. because the type system encodes much more information.
Though I always found Go to be significantly harder to read than Rust. Sure Rust has some crazy syntax at the edges, but Go makes it very hard to know where imports come from (and thus what they do), and the imperative style + lack of clarity about mutability makes code much harder to reason about.
I my self and teams members are slowly reading less code and requiring agents to prove things work the way we want in other ways.
The default sentiment is humans should read code it's more progressive and a leap of faith to start giving that up.
Obviously, I get why you feel humans still reading code is important, but if you look at the progress of AI for the past couple of years, that gap is closing. The trendlines speak of a future where it becomes less and less important.
This was exactly what happened with writing code. Now most people don't write code.
I use LLM daily to write code for and "with" me, I also write code without LLM. Most people I come across mix it up. A few do it all by hand, and equally few all by LLM I would say. Is that just in my corner of the world?
My entire company for example does not write a line of code. We manage agents and that's it. Many, many, many companies and people are already doing this.
Go is simple, no “magic” marcos or meta programming even with just a little programming in any language it’s not hard to understand what the go code is doing.
I have no doubt that you can get a LLM to write working bug free code in any language but that is not the topic of the article or my comment.
No way to know until someone does the science on this. Until then it's just people saying that more static checking is better. But I do think, anecdotally, python is horrible for LLMs.
Of course it can’t just be simplicity, it has to be “opinionated” simplicity. Rolls eyes.
Let's assume that you need to write a program with a given set of requirements, and that you have a magic wand that can instantiate a high quality implementation of the program in any programming language instantaneously and for free. My hot take is that you would not want to choose Go, and you would likely want to choose Rust.
The Go implementation will have higher memory and CPU consumption due to garbage collection, while still being subject to memory bugs. The Rust implementation would be as efficient as possible on the given hardware with minimum memory/CPU, and it would be immune to memory bugs.
In my view, the biggest challenge with Rust, and where Go wins, is the relative difficulty of writing in Rust as the language is significantly more complex. With LLMs this is becoming a non-issue, and we are getting ever closer to having this magic wand (I'd argue that for smaller programs the wand already exists today). The article advocates that Go has excellent readability. I agree that Go has trivial syntax, but given that it's so verbose, I actually find it easier to read Rust code. Its higher expressivity allows you to see the higher level intention of a piece of code more easily.
Many of the other benefits the article mentions for Go are equally applicable to Rust: compiler error messages are super detailed and a great help to coding agents, auto-formatting, a great language server, and a package ecosystem.
I guess from a pure language POV, one might argue that rust leaves humans with more opportunity to add abstractions that are too clever and too hard to wrap your head around. That doesn't feel like a strong argument, though.
Then there is of course the ecosystem, where go maybe has better libraries for some stuff (while rust may have better ones for other things).