So, depending on your goals, I think Rust is the better language in general. But if your goal is to get something done fast, then Go would probably be better, since it doesn't require that much learning effort.
You forgot pointers used to represent nullables.
Go was never ever intended for this purpose.
Can you explain? What do I set ‘score’ to when someone hasn’t sat the test yet?
You can have 100% type-safe, guaranteed at compile time code without null that can still represent the absence of data. Once you've used sum types, you feel clumsy when using Javascript, Python, Go, Ruby, C, C++, etc. especially when refactoring. Nullness infects your data model and always comes out of nowhere in production and ruins your day.
I can totally see this. I started writing a small cli tool in Go, and despite knowing way less Rust, I switched to it and was able to make a lot better progress at first due to pattern matching and result types. It was just so much easier/more ergonomic to write a simple parser.
The Go code was a mishmash of ugly structs and tons of null checking and special casing.
That was easy to understand.
> You can have 100% type-safe, guaranteed at compile time code without null that can still represent the absence of data.
If it's a single score, I'd still want to use null / int. There no invalid states being represented, anything else is still unnecessary complexity.
> Nullness infects your data model and always comes out of nowhere in production and ruins your day.
A TS example: trying to do anything with 'score' where score is `null | number`, would be caught be the compiler.
In your example, you still have to manually check if there's a value every time, but this is not compiler-enforced. Should you forget, you will get a runtime crash at some point (likely in production at a critical time) with some kind of arithmetic error. This wouldn't be possible with a simple sum type.
Also, a sum type with units of Score(Int) and NoScore won't allow assignments of any other "null" instances. Null in one spot is interchangeable with null in any other spot, and this can lead to bugs and runtime crashes. Null should be avoided when possible.
Wouldn’t I still have to check for NoScore?
> a sum type with units of Score(Int) and NoScore won't allow assignments of any other "null" instances.
I get this part - I wouldn’t be able to assign ‘NewBornBaby’ (my name null) to ‘NoScore’ (my score null)
> Wouldn’t I still have to check for NoScore?
No, because you differentiate between the sum type (e.g. Maybe in Haskell) and the number type at compile time. It's a small distinction - there will still be one or two places where you ask "is this a Maybe-score, or a Just-Score, or a No-Score", but the upside is that in all places you are very clear if a No-Score is possible, and you can't confuse the value with the error signal.
I.e. if you pass maybe-scores to something that computes the mean, you'll get a compiler error. The writer of the mean function doesn't need to care you've overloaded an error value onto your numbers.
The compiler support is the important part. Languages like C/C++ know sum-types just fine. They usually surface as sentinel values (NULL for ptrs, -1 for ints, etc) or unions with type fields. The stdlib offers it as std::optional<T>. As you progress along that spectrum, you get increasing compiler support there, as well.
One could even argue that sentinel values are a slightly better choice than Go's pairs, because they are closer to being sum-types than the strict product type that is go's (result, error) tuple - at least sentinels can't be simultaneously carrying a valid value and an error.
If I pass a null into something that calculates an average, taking numbers, the TS compiler will complain now. The writer of mean() (assuming mean() is typed) doesn’t have to know anything about my code.
That's right, and the compiler will reject programs where you don't do this. It's a set of safety rails for your code. You pay a dev-/compile-time cost in exchange for your programs not exploding at runtime.
> In your example, you still have to manually check if there's a value every time, but this is not compiler-enforced.
In rust, you would annotate score as `Option<u32>` (`u32` is one of Rust's integer types), and then you would set the score of someone who hasn't sat the test yet as `None`, and someone who got a 100 on the test as `Some(100)`.
Rust has NonZero versions of the unsigned types, so NonZeroU32 is the same size as a u32, four bytes with an unsigned integer in it, except it is never zero.
Option<NonZeroU32> promises to be exactly the same size as u32 was. Rust calls the space left by the unused zero value a "niche" and that's the perfect size of niche for None.
As a result you get the same machine code you'd have for a "normal" 32-bit unsigned integer with zero used as a sentinel value, but because Rust knows None isn't an integer, when you mistakenly try to add None to sixteen in some code deep in the software having forgotten to check for the sentinel you get a compile error, not a mysterious bug report from a customer where somehow it got 16 which was supposed to be impossible.
When a maintenance programmer ten years later decides actually zero is a possible value for this parameter as well as "None", there's a NonZeroU32, they swap it for u32, and the program works just fine - but because there's no niche left in u32 the type is now bigger.
> you would set the score of someone who hasn't sat the test yet as `None`
Yep that's what I expected. Emoji thumbs up.
In Rust (and Haskell and OCaml for that matter), there is no built-in null keyword. Option is just an enum in the library that happens to have a variant called None. So it's technically Option::None and Option::Some(x). But, really, it could be Quux and Quux::Bla and Quux::Boo(x) instead--without any language changes.
That is vastly better that what IntelliJ does for Java with their weird @NonNull annotations on references--which technically still can be the null. null is still a keyword there, and null is somehow a member of every reference type (but not of the other types--how arbitrary).
And C# has a null keyword, and the rules for type autoconverting it are complicated, and some things you just aren't allowed to do with null (even though they should be possible according to the rules) because then you'd see what mess they made there (you'd otherwise be able to figure out what the type of null is--and there's no "the" type there. null is basically still a member of every type. And that is bad).
So even the language used in "allowing values to be nullable by default" is insinuating a bad idea. Nullability is not necessarily a property that needs to exist on values in the first place (as far as the programming language is concerned).
What's special is that it's not like Go/Java/JS/etc where *every* pointer/reference can be null, so you have to constantly be on guard for it.
If I give you a Thing in Rust, you know it's a Thing and can use it as a Thing. If I give you an Option<Thing> then you know that it's either a Some or None.
If I give you a Thing in Go/Java/etc well, it could b nil. Java has Optionals...but even the Optional could be null...though it's a really really bad practice if it ever is...but it's technically *allowed* by the language. Rust doesn't allow such things and enforces it at the language and compiler level.
See these for reference
* https://kotlinlang.org/docs/null-safety.html
* https://dart.dev/null-safety
* https://docs.microsoft.com/en-us/dotnet/csharp/nullable-refe...
An orthogonal approach would be using a data type such as Maybe or Option, but ergonomics depends on language.
The "typical" Go nil-check would usually look something like this (no idea how code will look, apologies up front):
result, err := someFunction()
if err != nil { ...
It's nice that you're not having to litter your code with try/catch statements, or use a union type with an error value like in other languages, but the downside is that Go only checks to see whether err is used at some point (or makes you replace it with _), and it's possible to accidentally use err in a read-context and skip actually checking the value. Go won't prompt you that the error case is unhandled (in my experience)
In Rust, when you want to return a null-like value (None), you wrap it in Option<type>. To the compiler, Option<type> is a completely separate type, and it will not allow you to use it anywhere the interior type is expected until the option is unwrapped and the possible null value is handled. You'd do that like this:
var result = some_function()
match result {
Some(x) => handle_value(x),
None => handle_null(),
}The compiler forces you to unwrap result into its two possible underlying types (any possible <type> or None), and handle each case, which prevents an accidental null value being passed to handle_value. Trying to pass result directly into handle_value would give you a type check error, since it's expecting a <type> but is passed an Option<type>. The compiler will also give you an error if you try to only handle the Some(x) path without providing a case for None as well, so you can't just accidentally forget to handle the null case.
(For completeness, you can also just do result.unwrap() to get the inner value and panic if it is None, which can be useful in some cases like when you know it will always be filled, and you want to fully terminate if it somehow isn't).
So in your case (assuming this is in the context of a video game), you'd make score an Option<i32> for example, then unwrap it when you needed the actual value. Generally speaking, I'd make the score returned from a saved game loading function be Option<i32> and make the actual score for the current session just an i32, then the function that handles loading a game save into the current session would handle the Option<i32> from the save file (defaulting to 0 when this is None), and we could assume that the score would be set by the time the game session is running so we don't have to constantly unwrap it within the game logic itself.
Meanwhile my experience with Go has been the reverse. I’ve found it acceptable for most use cases, but for network services it really stands out. Goroutines <3
Goroutines don't have the restrictions of async that you must never block or spend too much time computing. Goroutines are preemptable. The language has memory-safe concurrency (except for maps, which is weird) and has garbage collection. So you can have parallelism without worrying too much about race conditions or leaks.
Go comes with very solid libraries for most server-side web things, because they're libraries Google uses internally. Rust crates have the usual open source problem - they get to 95%-99% debugged, but the unusual cases may not work right. Go has actual paid QA people.
Go has limited aims. It was created so that Google could write their internal server side stuff in something safer than C++ and faster than Python. It has a limited feature set. It's a practical tool.
I write hard stuff (a multi-thread metaverse viewer) in Rust, and easy web stuff (a data logger which updates a database) in Go. Use the right tool for the job.
Most of the time you can also avoid this by just copying data using .clone(). This adds a tiny bit of overhead, which is why it isn't a default - but it'll still be comparatively very efficient.
Similarly, there are facilities for shared mutation (Cell/RefCell) and for multiple owners extending the lifetime of a single piece of data (Rc/Arc). It's not that hard to assess where those might be needed, even in larger programs.
My understanding is you should operate the other way around. Things aren't safe for concurrent mutation unless it's explicitly documented as safe.
> So you can have parallelism without worrying too much about race conditions or leaks.
You might not worry, but I find these the two easiest classes of Go bug to find when entering new codebases ;).
Still, I agree Go is easier to get a web service up and running with.
Go's concurrency model is bog-standard shoot your foot off shared memory.
A channel is not magic, it's a multiple-producer multiple-consumer queue, you can unwittingly send a pointer over it (or a pointer-ish, like a hashmap) and boom you've got unchecked concurrent mutations, and in Go that even opens you up to data races (memory unsafety).
And because channels are slow, it's common to go down the stack, and hit further issues of mis-managing your mutexes or waitgroups, to say nothing of spawning a goroutine by closing over a mutable location.
You can do it right, in the same way you can do it right in C, C++, Java, Ruby, or Python. And arguably it's more difficult in Go because it drives you significantly more towards concurrency (and spawning tons of goroutines) without really giving you better tools to manage it (the only one I can think of is select).
thats hilarious, my daily driver language is elixir which is the goat for network services. I saw rust as the perfect compliment for that where I need everything else.
That said, Go isn't a very "convenient" language; there's not as much magic or magic libraries that come with the language that take over big chunks of your application, and the community at large actually recommends against using libraries in favor of just using the standard library.
And after a while, I... kind of agree? My HTTP API is gorilla/mux, which is only a thin layer over the standard library's HTTP server APIs (it adds routing / path matching). I started using Ent to abstract away my database, then switched to Gorm when I got annoyed at having to write so much code just to do inserts / updates and manually having to add / remove rows, but that one falls apart as soon as you have a data structure that maps to more than one level of tables deep.
I mean part of my troubles with databases is probably a disconnect between wanting to store items like whole documents but mapping them onto a relational database.
Golang
* Development speed: Golang wins by far. It's closer to Python in that regard, but with strong typing.
* Very nice multi-threading via Go routines and channels. Impressive semantics in simple syntax, requiring no synchronization mechanism on the user side.
* Large garbage collector penalty.
Rust
* Complete language with build system, crate, docs hosting.
* A lot more performance compared to Golang, on par with C++.
* Doctests (!).
* Slow to learn, slow to compile (probably not a deal-breaker, especially if you focus on microservices).
Concerning what would be a good usecase for Rust vs Golang, check this out:
https://discord.com/blog/why-discord-is-switching-from-go-to...
Except for all the times they are required and Go doesn’t tell you: https://eng.uber.com/data-race-patterns-in-go/
Go’s fundamental semantics are standard not-safe shared-memory multi threading. It provides an mpmc queue as a built-in out of necessity (since no generics originally, which would have made for an awkward situation), but really the only thing that’s notable about it is `select`, not `go` or `chan`.
In in some ways `go` is even a downgrade from other languages: you can’t get a handle on the goroutine and thus have to muck around with side-channels to even know that a subroutine has terminated let alone get its result.
You sound like you don't know why they explicitly refuse to add the ability to get a handle on the goroutine. If you do know, you are misleading people by omitting it.
* Go also includes the complete build system, package management (although it wasn't there from the beginning), code documentation, testing and fuzzing. Also the standard library is much more extensive than in Rust ("batteries included").
* Doctests: since you mention them explicitly, Go has those too: https://go.dev/blog/examples
* "Large garbage collector penalty": that obviously depends on your application and what you consider acceptable. I would say that in most cases the easier development enabled by having GC is worth it, but YMMV. Here's a discussion on the Go garbage collector: https://news.ycombinator.com/item?id=12042302
In my experience it's the slowest language to compile ever, and the binaries generated are gargantuan.
I was super excited to learn Rust, but that excitement is now 100% gone.
If I interpret the graphs correctly, I see:
Golang:
* baseline 20% cpu + spikes to 35% once the GC runs.
* response times of about 1ms + spikes up to 10ms.
Rust:
* baseline 12% cpu + flat, no spiking.
* response times of 20us + flat, no spiking (!).
In terms of scaling, I interpret the results in favor of Rust.
My reasoning is the more you run the GC, the bigger the penalty.
The TLDR is that, especially during GC, P99s and response times are notably worse in Go than Rust. Makes sense.
So I went with Rust and am very happy with the decision. Despite being a systems programming language, it feels surprisingly like a high-level language and I now default to programming stuff in Rust unless there's a strong reason to use NodeJS.
PS: That said, an often understated benefit of Go is that the community and job opportunities are massive in comparison to Rust (for now, at least).
Rust is a better c++. It's not appropriate for anything you wouldn't program in c++. The coding speed is slow
So if you are thinking about learning a new language to program your future apps you currently code in node, choose Go
The Rust language is a far better C++.
In practice, the compile time and binary size of Rust are out of control, which makes Rust far from being a slam dunk over C++. Crossing my fingers this will change!
The compile time story of rust and C++ is comparable, if you use it the same way. If you use deep include hierarchies and no precompiled headers, if you start using template heavy code like boost, or if you do code generation, the C++ compile times will quickly spiral out of control. Rust does not have the include problem, but the specialization/templating idea is shared with C++, and the code generation problem has an equivalent in the macro mechanism as used by e.g. serde.
In theory, you can get comparable compile times from both. Main difference is rust heavily emphasizes a programming strategy that depends on these 2, and it has a heavy cost in compile time. Meanwhile, a lot of the C++ code is still in the 'C-with-classes-and-every-vendor-creates-a-string-class' camp and while the abstraction level is lower, so is the compile time.
For the binary size, C++ can hide a lot of stuff in libraries, while rust compiles it in and duplicates it for each executable. So you pay a higher fixed cost per application. As long as rust has no stable ABI, rust will stay behind at this point. But it gets better optimization opportunities as it can merge the standard library code with yours, and inter library calls are more costly so runs wins there too. Presumably it's early day for a stable ABI in rust, big wins are still made. Long term, I'd personally like to see some ABI stability in the rust world.
But it's still something different than a real rust ABI. Basic things like pushing a string or an enum to a client will hurt. Providing a rust library without source is not an option for now.
Is there a report or study somewhere that shows how much it has improved?
I had heard improving compilation and build time was being worked on, but I don't get to use Rust much in my current work.
I would be interested to see how much improvement has been made and in what areas.
With Rust, you could use it to replace the most time critical parts of your high-level program piece by piece. The learning curve is then much easier, and adoption can be gradual.
Never done it myself, but:
https://www.ardanlabs.com/blog/2020/07/extending-python-with...
(Note that this is not a reimplementation of Python on top of CLR, but rather a bridge between CLR and CPython.)
The thing that makes FFI problematic in Go is green threads, which have their own stacks that nothing but Go understands. Thus, every FFI call has to arrange things to be what the callee expects, and you can't do async using goroutines across language boundaries (whereas callback-based solutions like promises work jsut fine).
Just like learning Haskel is a good exercise in understanding functional programming and lazy evaluation, which again will translate very well to the code you write as you will be able to identify pattens where functional programming can be applied.
However, neither language is really super applicable to general development, because there are hoops you have to jump through to write basic code where the language advantages are not really need, and other languages are much simpler and faster to develop in.
Golang is much more widely used for this reason, as its compiled yet features a gc, simpler to develop in with java contains a lot of good functionality in its stdlib.
I've learned Rust after having used Python, and at first I had a few "wtf" moments, things I just couldn't understand.
Everything fell into place after discussing these with a friend who knows much more about the "nitty-gritty" than I do.
I haven’t learned Rust yet, thought I’m quite keen to do so, but I have an (ancient) background in C, C++ and 8-bit assembly. I don’t find that I really use much of that knowledge when I work in Go, even though Go is still a lot closer to the metal than Node.
Anything where low-level control is required. It's not clear if there are true-Rust web apps in the wild (as opposed to web apps with some services in Rust); as far as I read, Rust web programming is ugly.
The market still offers few positions, largely dominated by crypto. I have the impression that it will still take many years before the field will move to Rust (where appropriate).
> Any advice on which I should pick as a new language to learn?
Depends on the concrete goals. If you want to make a career, Golang is the safe bet, by a very long stretch. If you want to have fun, try both, and you'll naturally find your inclination, as they have a radically different flavor.
There are. I run one. Written in pure Rust. 160k lines of Rust code in total, serving over 3 million HTTP requests per month. Best choice I've ever made.
Rust especially shines when you need to maintain a big project over a long period of time. People often say that Go is much more productive than Rust, and in most cases that is true, but as the size of your project increases and your expertise in the language increases this relationship inverts, and Rust starts to be much more productive. Pick a right tool for the job.
This might not be a satisfying answer for you, but I use my own framework. Its main selling point is that it can be compiled in two modes: during development it has zero dependencies and is blazingly fast to compile (it has its own minimal HTTP implementation, its own minimal executor, etc.), and for production it switches to use production-ready crates which everyone else uses (`hyper`, `tokio`, etc.)
Personally I'm not a fan of most frameworks which are commonly used in Rust webdev. The reason for that is twofold:
1) Most of them suffer from what I call the npm-syndrome, with hundreds of dependencies out of the box. Case in point, the minimal example from Warp's readme pulls in 146 crates.
2) They're often really complicated and have a lot of magic. I prefer simple functions with explicit control flow instead of layers upon layers of generics and macros stacked upon each other.
(DISCLAIMER: The following is purely my personal opinion; I'm not saying one approach is objectively better than the other, just stating what I prefer.)
For example, in Warp the way you add compression is by stacking a filter on top of your route:
let examples = warp::path("ex")
.and(warp::fs::dir("./examples/"))
.with(warp::compression::deflate());
In my framework you have an explicit function through which every request goes through, so if want to add compression you just call a function which takes a request and returns it: fn deflate(response: Response) -> Response { ... }
async fn server_main(request: Request) -> Response {
let response = ...;
let response = deflate(response);
//
return response;
}
There's no magic and you can clearly see exactly what's going on, and you can also easily add new transformations without the need to become a trait astronaut.I think that's a great solution because the biggest thing that makes me afraid of Rust webdev is compile times. Your solution seems perfect as you can get quick compile times during development.
Fellow npm-syndrome avoider.
I still use actix-web though since I found it way easier to parse than axum or warp, in my opinion. The minimal examples for each make actix-web the most readable for me.
Unless you need those extra nanoseconds of performance or super low-level features, Go will be a much better choice.
In the end, they are just tools, and you need to choose them based on your needs, not language features.
In the long run Rust's complexity will hurt newcomers(new to programming) while it will be a blessing for seasoned c and c++ devs. If all programming languages were tools, rust would be a very very specific tool which makes a lot of sense for a specific case. If nodejs and golang are tools, choosing one over another is easier as you can do same things in both easily with small effort. But you cannot rewrite all rust programs in nodejs or golang.
Finally you need to ask if rust is really worth picking over golang/nodejs for things that can be easily done in nodejs/golang. Rust is not for people who think is rust for them.
Arguments like some implementations are more elegant in some other language can always be brought up as arguments. They should only be taken into account when you run out of options to compare because they are exaggerated and subjective most of the times. For example(exaggerated) screaming why go doesn't have a borrower checker like rust makes no sense because go is garbage collected. For many people seeing such absence of features equate to lack of features in a programming language leading to more boilerplate or other downsides which is not necessarily true.
That said, I feel that Rust is likely the winner long term. So I'm still building my rust skills, but programming personal stuff in go.
Interesting; why do you think so?
At first glance this looks as if Rust would be more at home with polyglotism, but the typical Rust complement would be a hot performance critical part of something much bigger, and this is already deep in the realm of strategical commitment (all the not so hot parts have to buy in). Whereas Go often enters the picture in isolated one-shots and can grow from there.
I learned Go by reading The Go Programming Language. It's a bit old, but a very good book nonetheless.
I see Rust as more for people in systems programming who want improvements over C, rather than a desktop developer looking to learn something new. There's a lot of hurdles that you only really appreciate if you've come from an unsafe/low-level background
Here, Rust has officially climbed past NodeJS on the "cool" ladder. Let's rejoice, and welcome our fellow programmers into our communities !
And spite of some other comments, I found writing web servers in rust okay, and I think go is also fine for web services. And with go it also feels a bit like python when using other libraries, I don't know where to start. While rust with cargo is more similar to the npm experience
One of the reasons I started thinking which language to pick is when I started diving into web3 development. It seems like there is a trend into either using Go or Rust or both in some of the ecosystems. Think Tendermint, Cosmwasm, Solana, etc. While it makes sense to just learn both languages, I don’t think I have the mental capacity to learn both together quickly. It might work better to learn the one that has the most potential in the long run based on the trend.
TinyGo is an LLVM based compiler that targets microcontrollers but also has a WASM target and that creates considerably smaller binaries, but it doesn't fully support all of the Go standard library.
Ergo a a WASM Go application will be much smaller than those "modern" sites.
I bet even smaller than GMail and Google Docs.
Never tried it, though :)
Beyond things like borrow-checking; the language introduces a LOT of concepts that are quite foreign. Exposing yourself to them is good; because I expect that future languages will borrow heavily from Rust.
Go is a great language for the short term but I don't feel like it brings Anything unique or interesting to the profession. its only real advantage is that its quick to learn but there isn't much substance. Its a great language if you're the type of person who doesn't mind copying large reams of code to change a few lines for a new purpose.
If you can afford GC in your project go for Golang else Rust.
For example, generics in Go were criticized by some, praised by others.
You have the feeling that you can freely share your opinion in the go community without the risk of being harassed by the rest of the community.
In the rust community, just like a sect, everybody must say that everything is just perfect.
Passive / aggressive attitude is something I've seen a lot in the rust community.
I would suggest that if your plan is to learn C/C++ next, and you never really understood memory issues && pointers, then rust is a perfect choice at first.
I'm planning to learn Go next, I don't regret learning rust, I learned lots of things with it.
That's just not true.
Rust got already adopted by lot of either big or interesting to work at players (Amazon, Microsoft, DropBox, ...?) and, while anecdotal, I myself get also paid to program rust.
> the community is toxic. > In the rust community, just like a sect, everybody must say that everything is just perfect.
I often get the opposite feeling with all the diverse and lengthy discussions about how to do things, e.g., like getting async stable a few years ago or long blog articles of core contributors that state "we can do a lot better here and there" in public blog posts that get shared on /r/rust and don't get shunned.
There are very few open positions, though. Just check out the Rust newsletter - the open positions for each release can be counted on one hand.
I have the suspicions that Rust positions are typically filled in-house. Shopify, for example, adopted Rust, but AFAIK they did not hire anybody external to do so (nothing wrong with this, of course).
IMO there's only a tiny selection on that newsletter, it's just not a canonical source for rust jobs. E.g. and again anecdotal, we don't post our rust job openings there either as such more widely read publications are seldom a good fit, just like the monthly HN "who's hiring" thread - we don't want a flood of applications whom a good percentage of cannot even bother to read the few basic "must haves" for the job.
Also, in house fillings need employees that can program in rust too.
How so? I've seen the random drama crop up here and there, but it always seemed to mostly be about the "political" side of things, as opposed to the technical development.
What few interactions I've had with library maintainers and the tokio project have always been positive, and the people always seemed helpful.
> I founf myself in your same situation a few months ago. I chose Rust and regret it...
https://news.ycombinator.com/item?id=32105336
GP puts it well:
> Just like in any sect. As long as you agree everything is perfect, the community is the friendliest indeed.
The community isn't toxic as long as you happen to agree with it and praise Rust... Go figure.
At this point it's mostly a meme. Rust is slow to compile. I mean, yeah if you abuse meta programming or monomorphisation.
I've been programming in it, and while I like the language, I'm not on the language community bandwagon. E.g. CoC and it's enforcement (I think it's just pointless grandstanding).
Third: I said CoC is grandstanding. It's just a toothless document, that pretends to solve issues much like renaming Git default branch master->main.
We saw it wasn't enforceable last year when Rust moderators quit over being unable to enforce it.
The Rust community has been the friendliest PL community I've seen so far.
The community definitely acknowledges the limitations and sharp edges and listens to the users. Thanks to that attitude, Rust is way more friendly and easier to use than it was 5 years ago.
As of today, indeed.com lists 1,500 remote jobs mentioning Rust vs. 4,018 jobs mentioning Golang. That's not so bad. (However, there's no way to tell how many of those listings are Rust-specific as opposed to polyglot job descriptions.)
> Also, the [Rust] community is toxic.
Speaking slightly humorously, if you think Rust community is toxic, try expressing your dissatisfaction with Swift or Apple in the fanboi Swift community (controlled by Apple employees) and see what happens to you :).
Video games are not "serious", yet any C++ developer getting their chops in video game programming is not shunned for it.
I think "somewhat dogmatic" would be a more accurate description of the Rust community, IMO.
For example, I recently had a discussion about `enum` being a poor choice for what Rust makes it to mean from a C/C++ developer's point of view (which are Rust's main "replacement target" languages). The closest I got someone to agreeing with me is a sentiment along these lines "well, `variant` would may have been a better choice but it's not very familiar to C/C++ developers and, besides, when this decision was made, Rust had a hard limit of 5 characters on keyword length".
I've found the complete opposite, Rust communities are the least hostile programming environments I've come across.
There's also a huge amount of irony about saying a community is toxic on this site
Coming from a NodeJS background, Rust looks a tad more complicated but it looks cooler. There are also more job listings looking for Golang than Rust which makes me wonder if Golang might be a more rewarding investment?
What would be a good use case of Rust than Golang cannot do given its extra complexity and potentially lesser monetary reward? Any advice on which I should pick as a new language to learn?