No GC, manual and strict memory management
That's actually false. Rust has automatic memory management just like Go, and unlike C: you don't need to manually allocate and deallocate memory. It's more accurate to describe Rust has having compile-time memory management, rather than runtime memory management, just like the distinction between static and dynamic typing (while manual memory management would be analogous to writing assembly without types). I never found memory management in Rust any more diffcult than in Go.
Difficult to learn and slow to code
I would disagree with this. Rust is definitely a little harder to learn, but once I got the hang of it I was much more productive in Rust than Go. This is because Rust is often much more expressive than Go. For example, to sum up the squares of a slice of items in Rust I just need to do
some_slice.map(|x| x * x).sum()
while in Go I need something like
accum := 0
for _, value := range someSlice {
accum += value * value
}
Go also has no language-level prevention of race conditions, resource leaks, etc, and forgetting to defer
in the right place, lock the right mutex, etc often causes horrible consequences.
As for Go, it is deceptively easy to learn, but extremely amenable to hard-to-maintain spaghetti code if you don't rigorously document everything, due to things like the lack of generics, a statement-oriented rather than expression-oriented design leading to the use of a lot of dummy variables like accum
above, etc.
Go's concurrency model, as a language, is also horribly overrated. First of all, anything Go can do, Rust can also do with libraries like async-channel
, except with a more expressive type system and language.
I also think that Rust's async
model, despite the immature libraries at the moment, is one of the best ways of organizing highly concurrent, high-reliability network code (perhaps second to Erlang). For example, let's say you want to do "get webpage 1 and webpage 2 simultaneously, returning the first one that responded, and cancel if the whole thing takes too long". In Rust it'll just be
use smol::prelude::*;
use smol_timeout::TimeoutExt
...
get_webpage_1().race(get_webpage_2()).timeout(Duration::from_secs(60)).await?
Doing the same in Go would require spinning at least 2 more goroutines, setting up channels to cancel, etc, and it would be nontrivial to clean up your goroutines in all possible scenarios. In Rust all that is handled automatically.
The only advantages of Go in my experiences are more libraries and (much) faster compilation time. But Geph is largely designed from the ground up (it doesn't even use TLS in its core logic), and Rust's powerful language features mean you get a correct program in much less compile-debug cycles than Go, so on balance Rust is much more suitable for Geph than Go.