- Go is more fun if you are trying to be productive and push stuff out. The programming experience feels fluid and there’s not much agonizing over small details; the language is simple and you don’t need to think as much about things.
- Rust is more fun if you have a focus on perfection. It offers a lot of tools for abstraction and meta programming. These tools can be challenging at times. I do think even with NLL you will find yourself fighting the compiler, trying for example to resolve how you can avoid overlapping a borrow with a mutable borrow in some complicated bit of code, but you definitely get a lot of nice guarantees in exchange. I also do find it frustrating when something as simple as passing the result up can end up being really tricky.
There's truth in what you say, but it only describes the learning phase of Rust. Rust is quite challenging to learn and you spend a pretty long time in the uncomfortable place you describe. But one day, you end up internalizing the borrow checker's rules and you just don't think about it anymore and don't have any productivity penalty at all.
I don’t know how long it takes to fully get past stumbling through borrow checking and learning the intricacies of Result but it’s long enough to be a detriment. Obviously learning curve on its own is a downside, but also this complexity does not disappear when you understand it. It’s similar to, but less severe than, C++, in this regard.
I also think it depends heavily on the type of program you are writing and how. I’ve certainly hit cases where I still don’t know the optimal way of structuring things. In other cases people have managed to help me figure out what I need to do.
Concurrent memory safety is a huge plus, without a doubt, though there are applications where its not enough and applications where its too much. I think that puts Rust in a spot where it has use cases where it is clearly the best option but many use cases where it is overkill. As an example, Go shines particularly well for servers thanks to Goroutines and the fact that many servers have a shared-nothing architecture these days.
> I don’t know how long it takes to fully get past stumbling through borrow checking and learning the intricacies of Result but it’s long enough to be a detriment.
That's right, but no one expect to learn quantum physics in a few weeks either. Rust is indeed way longer to learn than Python, Javascript & others, but it's also much more powerful. And with the same level of power, both C and C++ are way harder to master than Rust (and arguably, nobody really master them in practice since even the most brilliant programmers shoot themselves in the foot from time to time. Yes, even DJB [1].
> Rust in a spot where it has use cases where it is clearly the best option but many use cases where it is overkill.
Indeed. It would make no sense to switch to Rust if Python is good enough for the task. I was just arguing that once you've learned Rust, you can do pretty much anything you want with it without friction, and I personally wouldn't bother writing anything in Python nowadays, because I can write Rust as fast and get the static typing guarantees and sane error handling that comes with it.
> Go shines particularly well for servers thanks to Goroutines and the fact that many servers have a shared-nothing architecture these days.
Having done quite a bit of Go, I don't agree with you. It's way too easy to accidentally share data between goroutines, and then cause data race or deadlocks . The day they introduced the race detector, we found 6 data races in our code (a few thousand loc) and a few others in our dependencies, and in the next year we found two not caught by the race detector (because it's a dynamic thing, it can't catch all races). More than generics (which are being introduced if they don't change their mind like they did for error handling) Go really need something akin to Send and Sync in Rust. M,.or maybe like Pony's capabilities system, but Go definitely needs improvement on that front. Multithreading is a hard thing, and Go makes it too easy to use, to people without the necessary experience (because Go is so easy it attracts a lot of junior or self-taught devs) without safety net and this generally doesn't end well.
- A trade off is a trade off; no need to justify it. Increased cognitive load is a con.
- Sorry your Go experience was bad. I can only say my anecdotal experience was the opposite. Mostly for shared nothing architectures, but I also worked on an MQ-style software in Go and had a relatively good time. I think things that are well-suited to CSP concurrency fare pretty OK. Rust could’ve prevented things like accidental concurrent map accesses, but it still can’t guarantee you are implementing concurrency correctly on the application level (from perspective of say, coherency or atomicity.) So for many apps I’ve written, even somewhat complicated ones, I don’t feel like Rust would always be the best option. To me Rust makes most sense when you really can’t ever afford a memory error. Web browsers seem like an obvious winning case.
While Rust can be technically superior to Go for a lot of use cases, Go has been most fun to program in for me for last 2-3 years. Coming from mostly Python/JS and having maintained systems in Java and Ruby as well, I still feel happiest when writing Go code. I don't know why but I think it's because I've never had deal with a system in Go where I had to peel layer after layer to find how something worked no matter who wrote it. All Go projects I've come across and contributed to have been extremely simple to read, understand and contribute to. _I think_ that is what makes me enjoy maintaining systems in Go so much.
Also not them, but I've worked quite a bit with both Golang and TypeScript.
I find TypeScript's interface flexibility to be pretty clutch when working with high-level code that deals with input that's.. Complex data structures. So I'm thinking configuration files, REST APIs, user/developer inputs. Having worked with many async paradigms, I also favor async/await for developing asynchronous business logic workflows. If you imagine your call graph for a certain workflow, and everything is written to use "async", you can imagine just drawing a circle around a portion of it and then easily "stamp out" more of those to occur in parallel. The way you can collect results and handle errors with the async/await paradigm is a bit nicer than working with channels and go-routines IMHO.
I like Golang for lower-level tooling and network services of course. It also has seamless support for parallel processing in process. The OPs project is something I would certainly look to Golang for.
Now on a tangent, C# has async/await and most of the speed but doesn't quite have the flexibility of TypeScript's interfaces and of course doesn't have the compile speed of Goglang. I would honestly use C#/F# a lot more or stuff if I thought it would fly in my work environment. Would love to work on some open source projects in C# to get it more exposure :)