Both can be true.
Rust is actually a very well designed language that takes the best ideas from FP (e.g. error/null handling wtih ADTs) where something like Go is stuck in the 80s without any sensible reason as to why.
The borrow checker and everything related to it is another matter but it actually solves the biggest hurdle in using e.g. C or C++ which are memory related bugs without any additional performance costs like with a garbage collector.
Well unless it's just a quick script, in which case Python will do just fine.
Tried Scala while learning Chisel and hate it from the bottom of my heart. It's like Kotlin on bad drugs.
My point is, people are different.
Weirdly Go has made me enjoy Python even less and compilation is so fast it's turned into my go-to for quick "scripts."
They also solve the problem of needing to hold the standard library in your head. When I'm working in Python, and I can't remember if the method to check whether a string has a particular prefix is `beginswith` or `startswith`, if I'm working in a REPL it's just a tab-complete away. In a language without a REPL, the solutions are "look it up online", "try both and see what works", and "you are using an IDE, right? RIGHT?"
This has become a sort-of gotcha for any discussions that involve comparing programming languages, but I think it has been over-extended beyond what is reasonable. It is true that some languages are much better at certain use cases than others, and especially if you consider their ecosystems when making this determination. For example, I don't feel Go makes a very good programming language for desktop applications or games, and there are some use cases where it is either not a good idea or flat-out non-viable due to limitations of its design.
However, I think the complaint of "intellectual masturbation" is definitely not invalid on these grounds. That's a far more general (and vague) complaint about language design. It's one thing to disagree with this assessment, but this counterpoint doesn't really address the assessment, it's just dismissing it.
That said, I do think that complaining of "intellectual masturbation" is still rather shallow. I think that if you were to compare the personalities of people who prefer Go vs people who prefer Rust you would find that the language design choices are not just intellectual masturbation, but they do reflect the priorities and mindsets of the people who design and use the language.
And that said, I think you could also make the argument that Rust has made some very costly decisions in the language design department to uphold its ideals. This does hit me when using Rust: It's not that there's anything wrong with it, but it absolutely 100% makes me appreciate where Go decided to cut the scope. Flat-out ignoring invalid UNICODE filenames may mean that Go is not suitable for programs that simply must deal with bag-o-bytes filenames gracefully, but on the flip side it sure does simplify just about every downstream decision regarding filenames. You can see this pattern repeat throughout the language. In some cases Rust goes through great pains to meet the ideals of those who love the zero-cost abstraction, but it does hit some awkward points. A point that I am always bringing up is the lack of the ability to directly allocate heap memory in safe Rust. With features like const generics, it's tempting to reduce indirections and flatten fixed-size buffers into your structs and so forth, but it's very easy to find yourself in a stack overflow if you do so, depending on the platform's default stack size. OTOH, I appreciate that in Go you don't really need to worry about a stack overflow, but Go's design decisions around the stack and goroutine do add some overhead to making C calls and stack allocations, which is a vastly different trade-off than Rust makes.
I'd say Go programmers can be categorized by the fact that many of them, myself included, actually like this pattern:
if err != nil {
return nil, fmt.Errorf("...: %w", err)
}
In Rust, you'd no doubt prefer to use one of the many error crates that cut down the boilerplate (somewhat, anyway) and let you use strongly-typed enums for your errors. I know I do this when using Rust, but the Go mindset is very different.I think both mindsets have value, and it's not surprising that people see Rust as intellectual masturbation to some degree, whereas people see Go as mindless boilerplate a la Java. Both assessments are too simple, of course. Rust feels like it will pay as much cost as it takes in the language complexity department to solve the problems they want to solve as fully as they can. Meanwhile, Go feels like it will spend several years trying to decide if adding a single major language feature is really worth the added complexity, and I think there's a zen to that. I don't think the answer is that they're built for different use cases, and their use cases freely overlap plenty; it's more like, they're built for different mindsets, and some of the use cases just wrap around that.