> Rust is overhyped
People are excited about Rust! Not sure why this is a reason you _shouldn't_ use the language.
> Rust projects decay
The text doesn't match the headline here; Rust takes backwards compatibility very seriously, and rust code I wrote in 2016 against Rust 1.10 still compiles with Rust 1.72 in 2023.
> Rust is still in beta
Mentions missing async traits, which is legitimately annoying, but the workaround with the async_trait crate works in practice
> The standard library is anemic
This is a tradeoff; big standard libraries become graveyards over time (the classic article on this: https://leancrew.com/all-this/2012/04/where-modules-go-to-di...). How long was Python stuck with a terrible HTTP client because that was the one in the standard library? In Rust we have an incredible, state of the art regex library because it's a separate crate and is allowed to evolve.
> async is hard
Rust's async is hard to get started with; it's a barrier to get over like learning the borrow checker and lifetime system. But once you do I've found it productive and incredibly performant.
--
Overall, I don't think that Rust is the right solution to all problems. Rust makes you think about everything you're doing, the ways in which your programs use resources, and every possible class of errors. This is incredibly useful for writing fast and correct software, but will be overhead for people who just want to move fast.
I also think that static memory management is not the right tradeoff for most application software, although a GC language with Rust's ergonomics and crate ecosystem would be amazing for those use cases.
I'd personally always choose Java over Go especially given recent developments like ZGC, GraalVM, and Project Loom which essentially makes Java a better Go.
> The text doesn't match the headline here; Rust takes backwards compatibility very seriously, and rust code I wrote in 2016 against Rust 1.10 still compiles with Rust 1.72 in 2023.
This hasn’t been my experience. Though it’s often not large changes that are needed. The bigger problem in my book is the crate ecosystem, which is riddled with abandonware. Though this issue plagues most all languages.
I agree with the reduction in development speed. But the cognitive load is less, at least for me. Rust's type system, error handling primitives, language server and compiler messages seem to guide and reduce the effort needed to write good programs. The reduced development speed is often an acceptable compromise for all the advantages Rust gives - especially the cognitive load. The language also seems to save a lot of debugging time - so the reduced development speed may not be of much consequence.
> Overall, I don't think that Rust is the right solution to all problems.
I guess this depends on how comfortable you are with the language. Rust is my second choice after shell scripts to automate things. The point is, your statement is correct for only a class of developers - those who are new to Rust. For others, it's just as good as any other language for almost all problems.
GraalVM is still nowhere near as nice as Go when you need to compile quickly. Last time I checked, the compiler needed orders of magnitude more time and memory to make a binary. ZGC is pretty nice, though.
Honestly, I find it much easier to move fast in Rust because for explorative code, I just bang out the code and used copy/clone liberally and once I have a skeleton it's usually a few iteration until rustc agrees to compile my code. Strong types makes it very easy for me to move fast. Doing this in C/C++ never worked for me and I always had to be extra careful lest I'd end up wasting a lot of time debugging.
I don't think Rust is over-hyped; almost everything I would have used Haskell for I do in Rust now.
As a Haskell fan this is very interesting! What sort of things do you write where you find Rust is a better fit? No code that I write in Haskell would be much better off without GC so I struggle to think of reasons Rust could be a better fit.
It compiles faster but that is about it. Which is a good thing too because it's verbose AF and heavily reliant on code generation even after generics shipped so that compiler lines/s actually matters.
The only knock you can put on Java for reliability is null-safety but lets be real, nil pointers, bad slice initalisation, etc are 10x worse in Go especially these days with @NotNull and powerful editors like IDEA stopping you from doing dumb things. Or simply using Kotlin which is non-nullable by default.
That and all the things Go is good at Java is simply better at. (especially once Java 21 ships in the next few days).
- Low pause GC? ZGC has Go beat, not just on pause times but on throughput and heap size scalability up into the terabytes. - Non-blocking code with synchronous coding style? Virtual Threads are much much better than goroutines. - Channels? ArrayDeque and friends are faster and have a lower learning curve.
Maybe the only area I think I prefer Go to JVM-land is the good parts of the stdlib. Go has lots of shit stdlib cough collections cough but there are some real gems. Namely the x509 and ASN.1 libraries are absolutely top notch.
Learning curve is also lower ofcourse, it's a very very simple language which is good for beginners and those taking their first steps out of JS/Ruby/Python into static types, pointers, etc.
Anyways, my real point was Java is easily faster and more reliable than Go and it seems pretty insane to reach the opposite conclusion if you have been on top of developments in both languages.
That said: A few design decisions in the Java language (that are only slowly getting fixed) harm performance:
1. "Everything is virtually dispatched" reduces the ability to make inlining decisions sensibly. 2. Escape analysis gets harder (and less effective), leading to moving fewer variables onto the stack. 3. The poor support for allocating compound data types on the stack.
All of these conspire to create many more heap allocations than comparable Go code, so even if the GC is much better, the amount of work it has to do is much bigger.
Achieving any form of data locality in Java is also hard because it's really hard to nest structs.
The Java design shows that the memory wall wasn't a thing yet when the language was designed...
Things are slowly getting fixed, and there's a lot of interesting off-mainstream stuff that can be done to get more perf in Java-Land (Azuls JVM, Graals AoT etc) - but the strange thing is that Java does pay for some outdated design choices while Go performs pretty well despite a very simplistic implementation...
you can use "static" keyword?..
> Escape analysis gets harder (and less effective), leading to moving fewer variables onto the stack.
does go have the same idea of escape analysis with benefits and issues?..
I work in Java for my day job and I disagree.
1. Cold starts for Java serverless (lambda) are worse than scripting languages
2. For everything else, Java uses 5-10x more memory than Go. The memory overhead difference is really noticeable while the CPU difference is often similar.
2. Most of the time, a signal that the wrong algorithms and data structures are being used
Amazon isn't rushing to rewrite their infrastrure from Java into Go.
Id be hesitant to use any VM dependant language in serverless... I mean I love elixir and built my startup on it but I'd never consider trying to run it as a lambda function for the same reason. You're fighting against the grain.
I've run plenty of Java applications in Lambda and they are pretty fast (like done in a few minutes fast). I've yet to try SnapStart which can make those workloads even faster.
2. If your Java code is using 5-10x more memory for the same task you are doing it wrong. Java objects do have higher overhead vs Go structs but not an order of magnitude. You could also be tuning the heap wrong, Java will use all the memory you give it and it won't be quick to give it back unless you tell it that it should.
Fighting with the JVM - even in modern versions - is an absolute pain. The practical reality of using _any_ JVM language is wasted memory footprint, classpath issues, weird dependency graphs because a mega-apache-project was used to solve a simple problem, etc. Never mind getting basic things like RPC clients over TLS (fighting with openssl and keystores? in 2023? really?) working.
> my real point was Java is easily faster and more reliable than Go and it seems pretty insane to reach the opposite conclusion
Citation needed. Disagree in practical observation.
https://discord.com/blog/why-discord-is-switching-from-go-to...
Yes there are lots of things that suck about Java and the JVM but you can't in good faith argue that it's slow and unreliable.
I'm so sick of these half-arsed "features" that somehow get adopted into Java code bases.
Stop what you're doing and go write a unit test for @NotNull (or @NonNull). Watch the null value happily bypass those "checks".
Or, use (or write) a notNull() method (I happen to use commons-lang3) and watch it actually work.
I mean you can literally assign nil to a "func" type, and then call that func and it'll panic at runtime. Neither the compiler nor the JetBrains IDE will warn you about that, and there are no @Nonnull type annotations you can add (even if they're not ideal as you rightly point out).
That literally happened to me last week, just a stupid coding mistake, but took quite a while to find. In Java IntelliJ would have probably warned me about that, and certainly if I'd added @Nonnull annotations.
FWIW, nullity control has been added to the Valhalla project, so it might be fixed going forward.
The decision made was to stick with Java.
Why? Because rewriting the long feature tail of the Java version in Go and ensuring bug-for-bug compatibility with the Java version would have taken multiple engineer-years. During the rewrite, from the perspective of the project's users, development would have stalled. It made more business sense to instead use those engineer-years to implement some new features that users were demanding. And after all, while the Java version's performance wasn't amazing, it was acceptable.
What does the golang standard lib have for that use case that Java doesn't have, or do better?
> but the argument is that forcing programmers to use a quite limited set of abstractions makes code more readable
There's a good balance. Sure you can probably argue that Scala opens the door for many different ways to write a program. But golang took the extreme opposite approach, resulting in very verbose code that is difficult to decipher. Java has a very solid middle ground here.
I think the static binary argument is a bit flat though.
With Java I don't even need to compile for multiple architectures, I can copy a fat-JAR onto any machine with a JVM and it will execute. i.e an artifact with exactly the same hash and no worries about Mac OS X DNS resolver weirdness or CGO nonsense.
That's going to need some justification. I work with Java and Go. I haven't worked with Virtual Threads yet but my understanding is Go's approach to goroutines and Java's approach to Virtual Threads are pretty much equivalent. (Channels, however, are quite different.) Let me know if I've missed something.
What sets VirtualThread apart is that all the support you get from the Java Stdlib. i.e ExecutorService and friends and now ThreadGroup with the improvements in Java 21. Not to mention the structured concurrency features that are planned to complement them. Another key difference is how much easier they interact with interrupts for cancelation without having to resort to context, channel and select hacks.
Compare this to Golang where this is very little tools for managing groups of goroutines. You have the sync package, specifically WaitGroup which get you some of the way there but it's still massively behind the equivalent JVM stdlib support for real concurrency. JVM has equivalents to everything in the sync package but in addition to that it for instance the collections library which contains ConcurrentHashMap, which naturally works perfectly with VirtualThreads vs Golang which map is not goroutine safe and you have to go outside the stdlib to get concurrent safe structures.
So yeah, if you are working in Java already you should checkout VirtualThread for your i/o intensive needs, especially if you were using Go for those tasks before.
- Hard problems that have concurrency, performance issues, or have to be highly reliable such as a database - use Rust.
In my experience Go does fine with a lot of concurrency and the GC can make some dirty lockfree tricks a lot easier. It also has a much more mature contribution story: Go test, go bench etc. work the same and proff endpoints in production are a godsend. We never really had a time we couldn't have used Go.
Rust has a slight performance advantage with some sharp edges around designing for the borrow checker, as well as much less fleshed out core set of libraries. The C interop story is better and async does work but can get messy.
Overall I think the tradeoffs are in ease of understanding, experience of team and tooling vs. the extra bit of performance, and can go either way.
Highly recommend sqlc.dev, goa.design, gokit.io, gql-gen, bind, and all the other code-generation libraries in Go.
Don't write all that code by hand. Figure out your domain objects, queries, revolvers, etc.., generate the code, then deploy it.
Go for all it's faults has one build system/tool and spits out machine code, hell it does that probably 10x faster than just tsc can typecheck.
Personally I don't like either but Go > Typescript seems like a no-brainer unless you are hell bent on the isomorphic code thing and all the extra work that entails. i.e. making sure someone doesn't reference window in an isomorphic lib or node APIs in the opposite scenario, etc.
Rust is even better, but not everyone wants the added complexity on their projects.
(also, I haven't worked with bun yet)
> They should be stable and move slowly so that most of the time of your develoeprs is not spent fighting with their tools.
I can't speak to Go's tooling base, but Rust's is head and shoulders above any other ecosystem that I've had to work with. This is definitely more a point in Rust's favor than against.
Here are some examples:
---
Rust Analyzer:
Clean build: 31.02s
Incremental build: 3.07s (Added a `println!` in a level-2 dependency in the dependency graph)
SLOC: 306,467
SLOC of dependencies: ~879,304 (After removing `win*` packages which make up for another 1.3M)
---
Zola:
Clean build: 24.58s
Incremental build: 1.34s (Added a `println!` in a level-2 dependency in the dependency graph)
SLOC: 17,233
SLOC of dependencies: ~2,087,781 (After removing `win*` packages which make up for another 1.3M)
Obviously, not all source code gets compiled due to conditional compilation but it makes for a good approximate if you only take into account 2/3 of it.
---
For comparison with Zig by building ZLS:
Clean build: 20.13s
Incremental build: 10.27s (I believe this builds the ZLS package again from scratch so not really incremental)
SLOC: 45,806
SLOC of dependencies: I don't know how to get this.
---
This was on a Ryzen 5600x
> Rust is the 14th most used language
I think the author is a bit confused about "most loved" - that means that people who already use it want to keep using it. 14th most used language is great for such a young and not beginner friendly language. It's only 1 place behind Go and that is 3 years older.
Additionally Rust is mainly replacing C/C++ codebases which are generally much older and slower moving than other languages.
> Now imagine being the developer tasked with updating the dependencies of a service that is 31 versions behind... > During the same period, there was 8 Go releases, 7 Node.js releases (but only 2 LTS) and 3 Python releases.
This is obvious nonsense. The stability of a language is not measured by the number of releases. Come on, did this guy really write a successful book about Rust? Is this satire?
> Rust is actually still in the beta phase, with some important features such as async Traits still missing, which brings more churn to the ecosystem.
Really? Is C++ "still in beta" because it doesn't have async?
> The standard library is anemic
Sure that is an issue in C++ where using third party libraries is a huge pain. Doesn't really matter so much when you can just `cargo add regex`.
> async is hard
This is the only vaguely valid point. But on the other hand 90% of the time the solution is simple: don't use async.
Very disappointing article. I was expecting an actual good comparison of the pros and cons. Go does have some notable advantages over Rust - compile time, ease of cross compilation, simplicity, goroutines, built in fuzzing support, arguably better dependency management. Why not talk about them?
At risk of starting a flame war, I don't find Python easy to use at all so I have to question anything the author says at this point.
I was first introduced to Python 25 years ago and stuck with QuickBasic, C and assembly. I recently tried to do some opencv stuff with Python and the dynamic typing made even the simplest things exhausting. Then there's the virtual environment and dependencies situation which is easy to make a mess of if you don't know about it upfront.
I found a C# library to do the same and was way more productive and finished the task at hand quickly.
Best advice you'll get is to try both (and more) and use the language you like best and that best aligns with the type of work you enjoy.
Despite its impressive compilation speed and bundled tooling and whatnot, some (myself included) find it tedious and uninteresting to program in Go, with tons of repetition and verboseness. Some people are more utilitarian and don't mind, but not all think the same.
But now, asking Go vs. Rust does not make sense at all.
If you want a mediocre speed application with fast development, use Go
If you want good memory footpeint with mediocre development use rust
I don't know if you can describe much of Kubernetes like that.
I know HN isn't a fan of "middlebrow dismissal" but go on, read it and tell me it says anything beyond "I like red better than blue"
It’s missing a subheading for “anytime you do not want a garbage collector” which is true for almost anything real-time / graphical etc
If you need to write microservices (especially for control planes where there good concurrency and distributed system patterns needed) - I find Go be a fine combination of performance (GC hit will be there over Rust), ease of deployment, programming model (CSP) - at a slight expense on verbosity (say compared to python and you also get used to this with your patterns).
If you need high perf/low latency/near C (embedded systems level) performance - with a type system assisted memory management - then Rust.
I have found Go's stdlib to be pretty thorough (and the ecosystem to be awesome too). Yes you will always find that set of X things hard to find that others dont care about. But horses for courses.
I have invested in learning both (but I also find learning languages a joy). But if you absolutely only have time for one consider your use case and pick appropriately. Yes you can do Rust for services too but given all this dual asyn model discussion still ongoing and a lot of real world services/control planes in Go there are already good Go patterns you can leverage right away at a much lower learning curve.
Go feels natural to me, Rust feels like an ugly looking, needlessly complicated language.
Go has decay too. Many packages are abandoned or not properly taken care of. Generics did their own to slow the language down. But even if it's not the fastest language, it's fast and robust enough to get things done. And that's what counts for me.
Go is ranked 13th. Seems weird to use language popularity as a criticism when you're only choosing between the 13th and 14th place options.
Besides, in 2023 their "All Respondents" usage is almost identical, with Rust showing stronger year-over-year growth than Go.
Most of them seem related to the way the community organizes itself, and what they value at any given moment.
What would a non-anemic STD look like? Could the STD be broken into smaller pieces while still being a standard library?
Async has been a point of major frustration for me from the onset. Some people love it some hate it. Is there a good way to appease both sides? What can be done to make the libraries more generic between the two? Having to reimplement everything for async is a nightmare.
As for feature bloat in general. I agree, Rust still feels sorta like beta software, but it’s also matured a lot. I’m not sire there’s an optimal rate of feature addition, though I do wish existing feature polish was a higher priority over new stuff. Funny, I was just thinking about this last night while I was stuck trying to fall asleep.
More like the standard libraries found in C++, Ada, Go, or Python.
Why can't Rust do something like C++ does with Boost?
If everyone is using a given crate (for example, serde) why not "adopt" it into the standard library? Give the maintainer a plaque that looks cool and a small fee for initial adoption and a recurring stipend for continued maintenance.
The crate becomes official, gets guaranteed maintenance and there is less need to reinvent the wheel or worry that a good crate will go unmaintained or have issues.
A few people have tried to make boost-like meta-packages in Rust over the years, but in practice, people don’t use them, and they die out.
Also, like, serde's main maintainer is also a member of the libs team, so it being moved into the standard library meaning more maintenance doesn't really make sense to me.
Or, if GC is not an option - like operating systems, embedded software, web engines and game engines. That said, why not just use Rust for everything if you know it?
https://www.youtube.com/watch?v=p-tb1ZfkwgQ
The general gist of the video is the creator prefer Rust for functional programming and programs without much state and Go for everything else. As someone who's coming from a React background I don't see why if Rust is brilliant for functional programming why it can't also be good for programs with state if the right design decisions are taken to handle it - can you not just use a redux style store with actions and reducers?
Rust, on the other hand, guarantees memory safety, pushes you to design better programs and cuts down on debugging time a lot. Rust is the better choice when correctness and performance matters. And if you are comfortable with Rust, it's good for almost any task.
> The general gist of the video is the creator prefer Rust for functional programming and programs without much state and Go for everything else.
Rust has no problems with handling states, as you guessed. They can't be global states (like in Go?). You have to group the state variables logically and pass them around. An additional constraint is that the data structures should be in a tree form. The ownership rules make it hard to have circular and mutual references in data structures (it's still possible with things like Rc and unsafe blocks).
Whether all this is an advantage or disadvantage really depends upon your preference. For example, I usually have a single large config object in my Python programs, whereas Rust forces me to split it up into manageable pieces. Frankly, I prefer the Rust style for multiple reasons: 1. Global states and circular references are an easy recipe for disastrous bugs. 2. Splitting up large state variables into smaller ones make it easier to reason about the purpose of each code section - it encourages more modular, refactorable and reusable code. (Splitting up data feels magical. All the problems seem to suddenly disappear when you reach a certain level of segregation) I haven't yet worked on a program that can't be written in Rust.
A ton of code, ML/AI etc goes through Python sooner or later. For example, as I understand it, PyTorch and Tensorflow, for instance, are written in C++, but primarily to be used in Python.
There are very few languages I know of that have compelling interop with Python. C, C++, Rust... Nim? All other major languages have something but as far as I can tell, it is usually some kind of hack/rpc kind of thing.
Clearly doesn't apply to every project, but one key reason why I'm learning Rust is precisely that I care about Python interior, and don't much love C++.
rust, java, etc are much more complex.
My question is why all the hate on Go? And if Go is so bad as these posts claim, why compare everything against it?
I'm not saying Rust isn't good or anything like that, but why the never ending hit pieces on Go? Lets just evaluate Rust or any language on its own merits.
I agree comparisons can be useful but its getting out of hand with these never ending Rust vs. Go pieces.
:P
Memory usage is pretty good with Go, yes. I'm skeptical how much this matters in a real world application, though.
It's the easy choice for new projects. And yeah, if/when it's time to optimize later, and the raw performance of V8 ain't enough, you can reach for threads, WASM, or Rust. 10/10 experience.
Zig is also a good option for that, but the language is still in development.
> Rust is (over)hyped
Whether it is or isn't, the content of the following paragraph does not justify the heading. It cites the StackOverflow surveys that says people like Rust and then cites adoption, but doesn't connect these points. It's possible for something to be hyped but not adopted much if it's new-ish.
The heading itself is also unclear. Is the author saying "overhyped" or "hyped"? Pick one.
Additionally, the author doesn't connect this heading to the overall article. They should explain why something being (over)hyped means you should not pick it.
> Rust projects decay
The rest of the paragraph talks about the Rust release cycle but doesn't connect the dots to why this causes Rust projects to decay.
Any Rust code written after the v1.0 release is guaranteed to compile forever. If you upgrade your compiler by 30 versions your code will still compile. A new release of Rust doesn't mean you have to drop everything you're doing and upgrade. If you want to upgrade once per year, you can do that.
The same points were raised on the author's previous article ("Programming Languages are Platforms") which was another article that raises points in the headings that are not described further in the paragraphs.
> Rust is still beta (despite the 1.0)
This paragraph says "related to the point above" but it's not related. In this section they say that Rust is missing features (it is) and in the previous section they were implying that it's bad that Rust is adding features.
This heading is also obviously intentionally inflammatory. If Rust not having async Traits makes it "beta", would the author have considered Go to be "beta" for 10+ years when it didn't have generics. Generics as a feature are *much* more integrated with fundamental parts of the language and cause ecosystem churn & split. See also Java and C#.
(For the record, I wouldn't consider either of those situations to be "beta" and think the suggestion is preposterous)
> The standard library is anemic
Meh, "anemic" is a pretty inflammatory word and I wouldn't go that far. It's intentionally bare bones to avoid bad design decisions that can't be removed in the future and so far that's been pretty successful.
Does the Go standard library even have map/filter yet?
It seems like this author's idea of a non-anemic standard library is that it has a builtin HTTP server. They also suggest in other articles that Rust needs to have a builtin templating language as well. They suggest that not having this builtin leads to bugs, as if a standard library can't have bugs as well? The link between these points is tenuous at best.
> async is hard
These paragraphs are pretty good.
___
All in all, it's a provacatively written article that's sure to generate discussion, and especially discussion unrelated to the article itself, but unfortunately there's little to no logical flow in the points that it's trying to make.
Is the Go standard library really considered rich? Coming from languages like python or ruby I found it pretty lacking. Admittedly I haven't used Go in 3 years.
With Rust you get a perfectly thought out packaging. You also get the best of both worlds - runtimes and threads. By design you are pushed hard to properly handle errors. Some of my large Rust projects take forever to compile, I'll give you that, but there is a good reason for it. The compiler is actually helpful and in a lot of the cases it tells you exactly what you need to fix when you mess up. And don't even get me started on performance. I have the exact same microservice implemented in both go and rust. And while I did not opt for the most performant rust web framework (poem), it's not even a race, it's a straight up massacre: when I benchmark the two with wrk, the difference in performance is literally 11 times - same database, same openapi specification, same logic. While the Rust standard library lacks a lot of things, even some basic functionalities, cargo takes care of it for you with 0 effort: cargo new whatever, echo 'rand = "0.8.4"' >> whatever/Cargo.toml and you are done.
Don't get me wrong, this is not a "bash-golang" comment. But I can't deny that when I put the two side by side, go looks like a toy language.
So yes, Go has its drawbacks. But it is easy to get things done with it.
Should I Rust or should I Go now?
If I Go there will be trouble!
If I Rust it will be double!
So you gotta let me know!
Should I Rust or should I Go?!
(I'll see myself out now...)
Rust for OS kernel programming, e.g https://github.com/dancrossnyc/rxv64
And go for practically anything outside that scope: web service, CLI tool, etc.