Rust has a mind-boggling overhead, for many reasons (and I'm not talking about the borrow checker, which I think one gets used to after some time), even if the language itself is consistent and ergonomic (within the intended constraints).
To me, they have very different use cases - one will definitely know when Rust is required or it's an appropriate pick. For the rest, Go is fine. I think that those who put them on the same basket, haven't really used one of them.
Regarding systems programming, my opinion is that they require the lack of a runtime (not just because of the performance, but also, for the framework(s) written with low-level primitives in mind), but this is arguable (in particular, there's no clearcut definition of what systems programming is).
I'm not saying everyone would fit in that camp and it is a harder language to get started in for sure, but I think the borrow checker scares away too many people. It is a learning curve, but when it clicks, you will realize that every language has ownership and borrowing... you just didn't realize it because the GC allowed you to be sloppy about it. Once you do, it makes you a better programmer (just like coding in Haskell does).
The overhead in Rust, when compared to comparable languages, is very concrete. On top of my head:
- using hash maps is more convoluted (in some cases, arrays also need some boilerplate as well)
- bidirectional/circual references need to be handled (and are also ugly); algorithms programming in Rust is typically more complex because of this
- lifetimes (which also spread virally when introduced)
- explicit allocation types
- (smart) pointer types in general
- interior mutability; which may also required additional design (including: will the mutexes destroy performance?)
Some of them intersect with each other and pile up (allocation types; pointer types; interior mutability).
There is certainly overhead in Golang (I think it's not very ergonomic for a functional style, for example), but it's nothing comparable.
Overhead takes time; unless one has a time machine, it makes a programming language concretely "slower".
The above is just the concrete overhead. The abstract overhead (=things to keep in mind) is another story (e.g. proliferation of types because of the ownership, traits...). I understand, say, that path types are a necessary evil, but they're surely ugly to handle.
> you just didn't realize it because the GC allowed you to be sloppy about it
It's not sloppy where it's not needed. A significant part of the Rust overhead is due to the rigorous philosophy of the language, which enforces constraints also when they're not required. This is absolutely fine, but it's not realistic to think that it has no cost.
Due to ability to work without stdlib, Rust is system language in a sense Go never will be, to the point Go authors withdrawn this definition.
> Is Rust really a suitable replacement for Go?
It depends on your requirements for the ecosystem. If you need compatibility with Go or Go libraries, than it's not a replacement.
Libraries and support aside, any program written in Go can be written in Rust (and going back to nostdlib, many programs written in Rust cannot be written in Go). If you have required libraries, I'd say it can be written comparably quickly and easy. For example you can have web service returning hello world in 10 lines of code or so in either.
They are popular in different circles, but that is mostly not related to technical abilities. For 99% of of applications, you could pick either one.
This is a good direction for Go, which will either lead to Go having a better ecosystem, or remove ideological barriers from people keeping on using Go.
Except then I'd have to learn Haskell or OCaml :) As a curly-bracket language programmer, Rust was much easier for me to get into and feels more like home.