My rule of thumb is Go is better for writing software, Rust is better for running software.
If I'm prototyping or experimenting, I'm much more productive in Go. If I have a well-specified protocol or something that works that I want to be faster, more secure, or importable via C ABI, I'd go Rust.
The separation for me is more about layers. If you're writing anything touching an OS, your choices are basically C, C++, Rust. If you're writing a web backend application, Rust isn't a good choice, and even Golang is questionable.
For back-end Rust is unbeatable if you are doing the kind of things where you need the performance for as little footprint as possible because getting twice as much server would be unaffordable.
But that also means that it is not necessary for pretty much every company out there except the biggest ones.
Rust is cool for interops though: you talk about the OS, but it's not just that, it's also integrating with other languages in a way managed languages can't do: you can use Rust in a Python app like you'd use C, and you can speed up critical section of your node App with it as well[1], this is where Rust shine. Not in competing with Go in online popularity contexts.
This is where I have finally landed on. I spent a lot of time over that past 15 years going through c/c++, (python|TS|go)* (almost in that order). My realization has eventually been for systems stuff c is great and ofcourse now if I can afford the learning curve then rust
For fe, I use ts with htmx for any server side rendering. I got very deep into nextjs enough to consider myself competent but code bloat and dependency breakages just got me off it
For backend/control planes like things nothing has come close to Go for me. It isn't perfect in any one axis, but has a bit of everything I need mixed (fast build speeds, CSP style concurrcy for managing orchestration related workflows, reasonably good typing, and runtime speed), well rounded stdlib, fewer dependency breakages and soon.
It's designed to be more CPU-efficient than NodeJS or Python, but if all your heavy lifting is really in Postgres and other services you're calling, it doesn't matter and it's a bit pedantic. I think Golang was designed for something in the middle, maybe building a DBMS or some deeper backend.
I strongly disagree with this statement, Golang is excellent for building backends and just the orchestration of all the services you are calling is better done in a typed/compiled language with great multi threading support and fast compilation times that is exactly what Golang excels at.
This is trying to solve a problem a lot of people never really had. I've never been working on an Express backend and thought gee, wish I had threading.
using a systems language for a backend mainly gains throughput over python than latency. each request might not be faster but you can handle 100x more users.
I primary write Rust/C for a living, but I would pick Go in any situation if I could. I understand Rust's appeal as a shiny spaceship, but it adds a lot of complication for not enough benefit if you can use a garbage collector. Why deal with boxing, lifetime annotations, and async when you could just write plain Go.
Go is easier for onboarding, it's fixed the major issues people have had with it - it has modules, it has generics. It's easy to package a binary versus deal with having a Python venv.
Go is just the best common denominator and that's what the majority of people need. I really feel that people want to use Rust because it's interesting and fun, not because it's really the better tool for the job. The vast majority of applications can use GC and are not resource constrained by Go's runtime or binary size.
I've successfully used ChatGPT and Gemini to 1:1 translate a pretty much all of my Python programs from the last 20 years (scripts really) to Go and couldn't be happier.
Instead of figuring out what's the package manager/virtual env wrangler du jour when installing my stuff to a new server after 2+ years of not touching it (Poetry is the current leader I think?) I can just compile the Go program with the correct arch on my local computer and scp it to the server.
In my experience, Go appears simple as long as you’re solving simple tasks. Once you need to model fairly complex semantics, whose structure and detail depend on your business domain, Go code turns illegible, with lots of hackily lumped together bloated nonsensical channels and for-selects stemming from async IO and multi-threading forced into the goroutines syntax, with hard to formulate structured concurrency. And then you bolt on your validation logic on top of it, with several Go idiosyncrasies, and then you need to explain the distinct consumer-side interfaces, underwhelming generics and myriads of conventions based rules. One could claim that’s not how one writes “good” Go code. But that’s what depends on the complexity and dynamism of your domain logic and the folks you work with. After Java, production grade Go for larger projects is terrible. Null pointer method receivers, interface reification. And now the experiment with the functorial ranges, increasingly with more and more genetics, all without any syntactic sugar… hard to read, hard to explain.
Oh and the GC is rather inefficient compared to most JDK distributions. Compared to modern Java or Kotlin, for my project requirements, I don’t want to do as much Go as I used to. JDK Mission Control and Flight Recorder alone with great IDEs and profilers are golden. And you pay in RAM for JDK apps.
As for Rust, it just requires more upfront cost, but makes you consider potential failures at every step. Debugging production code isn’t fun, fuzz tests aren’t enough to assure quality to the extent Rust’s type system can. I trust rustc much more than I trust myself or other devs. If the code passes rustc, and the type semantics are correct, I’m 3/4 certain the code is correct, that’s a very high watermark, albeit at the cost of the upfront effort to satisfy the type constraints. Much more efficient in terms of dev time than debugging Python or Go at runtime.
Anyway, one can easily run many Python packages on GraalVM Truffle for direct interfacing with Java, Ruby, R, and via PyO3 with Rust, for which you have the native Polars data frame library, which all cover a good chunk of Python programs. Rust also teaches one to do proper ownership accounting for the variable bindings, great for C++ devs and for heap escape analysis by inspection for Go devs alike. Lots of Go bugs result from lack of understanding of ownership and implicit reference binding as opposed to copy and move semantics. Some of that was now “improved” with Go 1.22 for closures in loops.
Not OP but between Java and C# it's hard to not to lean Java for the absolutely massive lead in high quality libraries and ecosystem support. C# still feels like the new kid in open source circles though the languages are 90% the same.
This kind of response is a common issue .NET has to deal with. C# is not Java, I wish it was tongue in cheek but I keep having to seriously respond to these, as unfortunate as it is.
First OSS version of .NET was released 8 years ago.
Java is much higher level and much more OOP focused language than C# of today, which is multi-paradigm and exposes a lot of low-level features when needed, and is implemented under the hood way closer to the likes of C++ and Rust.
The difference in quality is dependent on the context. If a company is a pure Java shop that lives and breathes Apache projects - sure. Not so much or opposite otherwise.
years ago we switched from python to go. super happy we didnt go for rust, C++ or elixir. go is the get stuff done and make it fast language. my startup would have had a hard time and not grown as much if it wasn't for go
If you really want "worse is better," it's Javascript. Idk what the use case is here exactly, but if the thing worked in Python, JS was probably a fit.
That's cool if you're happy with Go. I'm pretty sure you'd have been equally happy going to Rust though. Once you go over the first few days of learning curve Rust is very similar to Go I'm terms of productivity.
I like the syntax and type system more in Rust, but at the end of the day the language are pretty similar in terms of developer experience if you're doing back end stuff[1].
(Fun fact I learned Rust and Go roughly at the same time in 2015, and Go's tutorial was a big help for my understanding of concurrent programming in Rust, with channels and mutexes, for someone who came from a JavaScript background and had never been exposed to threads before).
[1] A cool thing about Rust is that you can use it to learn new stuff that aren't web back-end, but that's a good reason to pick it for side projects, not for using it as a company.
Edit: four downvotes in three minute? I must have say something offensive…
The difference between Go and Rust is that I can (and have) teach any Java coder to be productive in Go in about a week.
I couldn't teach _myself_ Rust in a week.
Yes, if you're making something where being Correct is a hard requirement - Rust is perfect. But you do need to acknowledge that there is a definite learning curve and the average Job Coder (works from 9-5 and doesn't think about it on their free time) isn't cut out for Rust.
If your team is hand-picked 10x coders, Rust is again by far the best choice. It's got fancy PL bells and whistles that keep the dopamine running for experienced people =)
> The difference between Go and Rust is that I can (and have) teach any Java coder to be productive in Go in about a week.
> I couldn't teach _myself_ Rust in a week.
Autonomous teaching is supposed to be harder than with a tutor in any domain so it's not particularly surprising ;).
> But you do need to acknowledge that there is a definite learning curve
I don't like the “learning curve” phrase for Rust, because the curve itself is actually fine.
But before you can even enter the learning curve there's a significant step to cross. It's not particularly difficult, but it's all about theory and concepts. It's like high-school level trigonometry, it's not particularly hard, but it's still something a bit dry and that needs motivation to learn.
With a teacher and assignments, most people can do it, but without it you really need to make the effort of understanding the core concept (Ownership, borrowing, Send and Sync, + heap and stack if you don't know about it before hands + what are threads, data race and locks[1]) before you can even start to get to the fun part of learning a new language.
> and the average Job Coder (works from 9-5 and doesn't think about it on their free time) isn't cut out for Rust.
Without an external motivation source, the average developer has no reason to have the motivation to cross this learning step.
But as part of my job, I've thought Rust to average Joe in a week and they became productive quickly. I'm sure I could teach you Rust in a week ;).
[1]: the deadlock empire is an excellent learning resource for that one.
Sure, but you can teach yourself Go in a couple of days, likely having running code from the get go. I think with Rust you will have more frustrating interactions with mr. compiler in the beginning.
Interesting. I only butted heads with Golang in the second phase of use. This is when we were fed the mantra of "you're not doing it right" and "the go way" (which turned out to be true.) This was an unusual experience for me in terms of programming. Rust (never tried beyond reading the spec :) per comments over the years also has that feature but unlike Go it is not something you can just pick up in a day. I released the initial working cut of an OSS driver for a DB 3 days after Go was released. I doubt I could do the same with Rust.
I think rust and go are similar on the first run through it’s once you hit lifetimes that things get confusing for complex things, but then if people would start properly name lifetimes in their code instead of just tagging everything with the same lifetime name or worse the same anonymous lifetime they’d more easily understand why most lifetime errors are happening.
First of all, disagreeing with someone's assessment of learning difficulty isn't something that should deserve downvotes at all.
And then I've been working in Rust with beginner and mentoring them while they learned Rust, and I can assure you that the difficult part that most people struggle with is just half a days of learning actually[1]. Then you put in practice with exercises, to familiarize yourself with the syntax and the std lib, for a few days and you're ready to code.
The difficulty is to overcome the first step of assimilating concepts, that you need to unlock the next steps. If you skip the concept phase, then you can remain confused for a while I guess.
[1]: I've just check my slide deck, Ownership + Borrowing + Arc/Rc + RefCell/Mutex + Lifetimes + Send + Sync, the entire package of Rust hardcore concept that everybody struggles with, fits in 63 slides, with the exercises, and I usually cover it in half a day. And it's accessible to pretty much everyone without prior Rust or C++ experience. I even re-explain what a thread and what the heap are.
I'm not a downvoter, but in my experience Rust was a learning curve even after a month, causing me to switch a project (software-defined network research prototype) mostly back to C.
It depends where you come from and how surrounded you are with people familiar with the language. If you're working on your own, it can take some time for the key concepts to click. But if you have a mentor that can help you go through the core concepts, then it can be pretty quick.
I've been on both sides, I leaned Rust very early and it took me a while to even understand what lifetimes were and wth was `Copy` and `static`, but after that I've been onboarding complete beginners at several companies and they got proficient very quickly with some guidance from me for key concepts.
Rust isn't hard, it's just has a few concepts that you need to understand otherwise you're just confused by everything you encounter. But to me wasn't not too different from the effort it took me to understand "wtf are prototypes" when learning JavaScript 15 years ago.
When you come from a certain language paradigm and you're learning a language with another paradigm everything sounds so confusing at first, even though the difference aren't actually that big in reality. But you need to be able to overcome the difference before you see the similarities.
It was indeed only me working on it. I forget what was the issue exactly, something about constantly forgetting what the "mut", "&", "*", etc symbols did in different contexts. I conceptually understood it since a lot of things were similar to the N languages I already knew, but the syntax was a lot.
You really should use whatever works best in the situation. Languages are tools. Javascript, Typescript, C, C++, C#, Java, Go, Rust, Zig, etc all have their strengths and weaknesses. It's a mistake to typecast yourself as a specific kind of programmer. Technologies change all the time.
Languages are tools - yes, but different languages aren't necessarily different kinds of tools. When we talk of actual tools, we need wrenches, screw drivers, pliers, hammers, etc. Some of these languages you mentioned are more like different brands of tools rather than different kinds of tools, e.g. Java and C#. One is Husky, the other is Craftsman - that is, they're the same tool.
Now if you said you need a systems language, a scripting language, an imperative language, an object-oriented language, a functional language, a logic language, a matrix language, and a lispy language in your toolbox, then sure - that makes sense. But in my experience that is not what people are saying, and that's why I'm pushing back on this way of thinking.
The title is just a bait, the article doesn't really compare them it just implements the same thing in both languages and conclude:
> This project has come into existence over the past couple of weeks of hacking late nights and early mornings. At times I felt like I was building a plane during take-off – especially the Rust code parts which I was literally picking up along the way. It’s been a tremendous fun experience I’ve really enjoyed. It made me appreciate both Go and Rust in different ways as similar yet so different programming languages.
Lol, i hate the tons of crap I already have to keep in mind and do. Advice like this is what drives the suicide rates up. Expecting people to just "learn a language" like this is a sign of a psycho to me anymore. I totally concede I'm not cutout for the work though and just absolutely hate my life as a software engineer, and reading comments like this is why I take heart medication now.
Just ask ChatGPT questions like "how the hell do I do (something in the language you know) in (the language you don't know)." And you'll never get an answer like "actually the language doesn't have this feature," it'll just tell you how to do basically what you wanted.
There are only a handful of paradigms used in industry. After you learn them, switching programming languages becomes trivial as far as mental strain goes. This seriously should not make anyone feel anything close to suicidal. I hope you can find help for the trouble you are going though <3
> Does it follow that brainf*ck is as good as any other language
No, it follows that you are competent enough to know what problems you're trying to solve and then look into which ecosystem has the best features for solving those problems.
>> I love Go. In spite of all its quirks and foot guns ... programming in Go for ... a decade
Why do so many go devs feel the need to make statements like this. Go has issues, the are well known and easy to work with/around. Every language has these, every single one.
Also GO, and rust (and zig for that matter) have all sort of found their lanes at this point. Candidly the constant comparisons between the two (when they are much more complimentary) is getting tired.
I think it is to pre-emptively dismiss inevitable common trope criticisms made about Go. I don't think they truly believe this, it's just the common pattern of speaking in intellectually adversarial discussions in 2020+.
- Acknowledge the common criticism
- Defeat it with appropriate common retort, or make a small concession
- Proceed with the meat of the argument with your most common opponent "disarmed"
Mention how NodeJS has simple package management while Python doesn't, you'll find the Python apologists explaining why somehow it was an impossible task for Python to do packages right for legacy reasons, even though they got to force a whole breaking 2->3 version change.
Also bring up the GIL, and you'll be told how Python is implementation-agnostic.
Packaging is indeed a weakness of Python, but to be fair, that Python packages are frequently wrapping C, C++ or Fortran code makes packaging a lot harder compared to nodejs.
Ehh, those communities have their equivalent issues.
At least for Python it's some combination of: I know Py3 was a nightmare and packaging in general is a dumpster fire, testing is a constellation of incompatible tools and practices, MyPy and progressive typing is an embarrassing half-baked mess, and deployment is only really possible when you bundle an entire system image into a container— but hey, developer productivity right?
The sad thing is Go doesn’t need help - it won. It reached critical point where no matter how shitty it is in practice, it will be worked around and made work because engineers have no other choice - that’s what companies impose on them.
Like with Python and ML.
The optimal amount of bullying towards Go and its proponents is always “more”.
Having worked in many languages including Go and Rust, I commonly see the following.
1. Team uses some interpreted language. This language is fine for most of their work, but causes performance problems and/or the team needs to do something performance sensitive.
2. Someone on the team proposes Go, often because it solves the performance problem - and is very simple to use. This proposal invites suggestions from the organizations programming language experts leading to "let's use lang X" suggestions. Often these suggestions have recommendations based on advanced programming language features such as high-order types, functional paradigms etc.
As Rust has been somewhat popular for backend services, you will find many suggestions of "let's use Rust." These discussions can often be less than civil. As I've aged - I've moved closer to the advanced language features camp - but I'd doubt that this is actually beneficial for productivity. It took me 3 attempts to learn the language and 5 years for Rust to feel productive - now it's my preferred language for side projects. Go took less than a day to pick up.
> It took me 3 attempts to learn the language and 5 years for Rust to feel productive - now it's my preferred language for side projects. Go took less than a day to pick up.
This is the bit people keep overlooking (maybe intentionally). Yes you, polyglot coder who knows 15 different programming languages and has 15 years of experience on the field can learn Rust in an afternoon and do a flawless solution on Advent of Code with it while learning.
But 99% of the people working in software (you know, all of the people outside FAANG and F500 companies) know exactly one language and have no interest in learning a new one, especially one that's really complex and full of fancy features they don't know what to do with.
I don't know if it's really still a fair trope at this point, but the argument made is that Go was specifically designed to be the best of Google's three main languages at the time— C++, Java, and Python. It was made to be quick to learn, hard to mess up, and easy to read/review. It specifically includes things like the build tool and formatter because those are long-running pain points in large scale development.
Rust, on the other hand, is a borderline research language that was built to support Servo, a web browser backend— literally among the hairiest of sofware engineering problems in existence. It gives you a lot of "safety" but at the cost of having to consider issues that most developers never think about.
This is not to say that Go is for dumb programmers and Rust is for smart ones or anything of that sort— just that despite years of evolution, both carry the DNA of their inception, and it shows.
> This is not to say that Go is for dumb programmers and Rust is for smart ones or anything of that sort
Go ahead and say it; I don't mind being the dumb programmer who gets shit done.
After all,
> Rust, on the other hand, is a borderline research language
It's ironic that the "smart" programmers are using their new and novel language to mostly rewrite existing stuff, while the "dumb" programmers were delivering new and novel shit using the "dumb" language.
This is exactly so. At the edge, the go community will debate whether the language should be used for a project at all. Whereas the rust community will ship something that only kinda sorta works - or takes performance above all as the primary motivator.
As a very experienced engineer, I like the idea of Rust being a go to for all problems. 10 years ago - I would have hated its complexity and cursed the TL who forced it on my project.
The higher or lower learning curve for a language has no impact on when you stop learning, only on when you stop learning the language (or making significant gains in learning the language, since there's likely some corner you still don't know or know well).
If you stop learning just because you've mastered a language and learning the language was not your actual goal, you've failed. You should continue learning by applying the language to solve problems, which, unless you solve the same things over and over again, offers plenty of opportunities for continued learning.
You're just experiencing time passing on the internet. Some discussions spring eternal, because there's a constant stream of people having it for the first time.
It’s frustration at having to learn more than one programming language.
At this time, due to the social integration of technology the number of people who interact with development has far out paced the number of people who enjoy development.
> they are much more complimentary
If you hate writing code but do it for your job, then you are going to really hate writing code in two different languages with their own syntax and paradigms.
Also, nearly all programming language projects want to be the “everything language” so essentially any language is a fine choice and what it really comes down to is the people who enjoy the work develop “tastes” and “preferences” that they treat as dogma when defending their language of choice.
> It’s frustration at having to learn more than one programming language.
Imagine bob ross with only one color could still make something magnificent, but what could he do with two colors? You can't have Burnt Umber without some Phthalo Green..
Due the concept of Turing completeness I’d argue it’s more of deciding which paint brand to use, or if you must, I suppose you could liken it to the distinction between choosing oils or acrylics.
You don't actually understand Turing completeness if that's your takeaway.
Turing completeness is about computational equivalence. That, fundamentally, any Turing complete language can perform the same classes of computations as any other. It says nothing about substitutability of one language for another within any other context.
> If you hate writing code but do it for your job, then you are going to really hate writing code in two different languages with their own syntax and paradigms.
I don't wish for this, but sometimes I wonder how different the industry would be today if dev salaries had remained in "respectable but nothing amazing" territory.
Maybe it's just nostalgia goggles, but when I was getting started ~35 years ago, I think it was rare to run into someone who hated writing code but did it for their job. There were other much more profitable jobs for people who were looking to be paid as well as possible for work they hated.
They've found their lanes now, but I think there's still a lot a historical baggage in the discourse from back when they were much closer together— Go thought it was competing with C++ rather than Python, and Rust originally had a much bigger runtime before no_std.
> Why do so many go devs feel the need to make statements like this
This is a common conceit when writing for the sort of audience who might, for example, nitpick something as utterly uncontroversial as an author's disclaimer acknowledging common criticisms of a language they enjoy working with.
Golang recently folded on the whole "no generics" decision, which throws a lot of dust into the air. Personally I'm waiting for them to add exceptions and async/await.
Fair enough. Just keep in mind that in the common runtimes of the most popular language, JavaScript, your async/await code is usually a single threaded event loop. Which is very different from Go's green-threads implementation.
I don't want to have to make a channel every time for something so simple.
Also, was Googling how you execute two things at once then wait on both in Golang, and https://www.reddit.com/r/golang/comments/15xp94w/asyncawait_... came up. This is honestly how I judge ease of use, how simple are answers to simple questions. The agreed-upon response was to use a library.
Channels and `async/await` are orthogonal. Channels are a way of communicating and coordinating between concurrent tasks; `async/await` are an alternative to blocking function calls (or an alternative form of blocking function calls, perhaps). There are implementations of channels for environments with `async/await`, where you would use syntax like `value = await channel.receive()`.
What you may be getting at is that in an environment like Node.js, where everything runs in a single OS thread and there is no parallelism, there's a reduced need for coordination features like channels (or mutexes), because it's safe to mutate shared memory. But that too is orthogonal to `async/await`: the Python library gevent, for example, uses ordinary blocking function calls while running concurrent code in a single OS thread, making it safe to mutate shared memory; and conversely, C# allows `async/await` to be executed across multiple OS threads, making it unsafe to mutate shared memory.
What I mean is, to do the equivalent of async/await in Golang, you need to use channels. As I understand it, you can wait on a goroutine to finish by waiting on its channel to return something. Async/await would simply be syntactical sugar on top of that, it's already close.
One implication of async/await is that you need some kind of greenthreading or thread pool because you really don't want to spawn OS threads for it. In JS it's an event loop, Python and (I think) Rust have that too now as a lib, and Golang already has its own greenthreads.
And btw, the reason JS doesn't have threading is because for those applications, you don't need fast communication between parallel tasks like the things Golang is made for. NodeJS supports subprocessing, and the tasks will probably not talk to each other at all, though there's IPC if you really want it.
You don't need to always use channels in Go. You can use the facilities of the sync package (https://pkg.go.dev/sync) to communicate across go-routines.
If I'm prototyping or experimenting, I'm much more productive in Go. If I have a well-specified protocol or something that works that I want to be faster, more secure, or importable via C ABI, I'd go Rust.
In practice this means I almost never use Rust.