You don’t need to know much more than Python/Ruby to get something done in Go, whereas Rust needs a C++ or Scala or Haskell or whatever background.
Rust places too much mental workload on a programmer to make the compiler happy.
The Go compiler is much more human friendly.
Swift is a nice mix of all worlds, IMHO. Would be nice to see that get more server-side use.
At our Scala-centric company, Go gets used a lot more for one off tasks and microservices.
We rebuilt one Go service in Rust just to get familiar with it and no one has written more Rust since.
I think it would be good if one dabbles a bit with both and pick one which one feels resonance with. That being said probably one need to give a bit longer time for Rust to be comfortable with it.
Ouch, OOP in Go is just asking for a trouble. "Inheritance" by embedding anonymous struct/interface should be rarely used. Playing with a magic dependency injection, reflection mocking often do not leads to anything good too.
> In addition in Go I find the project setup and settings like GOPATH, GOBIN quite confusing.
I guess you work on Linux :) Yeah, it is weird, I am glad they have improved that flow by guessing empty GOPATH will be equal to $USER/go/ directory. GOBIN is actually not needed, only if you have used dep dependency manager, which for many years is deprecated.
Well here I am to deny it. I personally find Go super hard to write anything that is not a few lines of glue code (and in that case I just reach for Node).
Rust made me lazy. It's just so easy to be guided by the compiler and the architecture that emerges naturally is just so beautiful and easy to navigate.
I don't like Rust for its safety guarantees, I just find it pleasurable to write and even better to read. Safety is just a plus.
I'm not saying this is a universal truth though, Rust just fits my mental model. It isn't even a matter of past experience: I code frontend JS for a living (though I've been exposed to all kinds of code throughout the years) and I actually enjoy JS.
I tried really hard to like Go. I just couldn't.
> I tried really hard to like Go. I just couldn't.
I would expect something opposite for most of programmers. Especially, because Rust support in VSCode/JetBrains IDEs was not very good for many years. However, during talks with various people, I have noticed the Go was natural choice for many former Python or Ruby devs, while Node/Java guys had problem with adapting to it.
Personally, when I take a look at the Rust code it feels like some ECMA Script in a compiled world.
Swift's Codable is doing code gen under the hood, so it also has a binary size and compile time cost.
Swift also doesn't scale that well with core size like many other languages do, so your compile time is not easily fixable with large thread ripper style workstations.
Do you have similar issues with golang and rust? At least golang was designed to be compiled fast.
Compile times are definitely a pain point in Rust, but from what I've heard the Rust compiler is pretty good at scaling to multiple cores (my machine only has 2, so personally that doesn't help much).
“Needs” is a bit strong but “may find some things familiar and therefore easier” is a common refrain.
fn foo() -> &str {
&String::from("foo")
}
Does not work. Whereas coming from C or C++, you will appreciate the safety guarantees the borrow checker is giving you.Learning Rust coming from an OO background is also hard, as you have to adapt to the more functional approach of the Rust type system.
As for your example, even C and C++ devs would squint a bit at why that code doesn't compile: you're allocating a string on the heap, so why can't you return a pointer to it? Also, I think str vs. String is usually confusing at first, regardless of your background.
I would say that the relationship between str and String was what most surprised me. I at first assumed the underlying primitive would be String since str is what you get when you borrow from a String, but it isn't. str is a built-in, whereas String is just a type defined in the (optional, this is a systems language) standard library.
If your environment can't afford memory allocation, you can't have Strings but you can use str just fine, that's a built-in. Since you lack allocators obviously you won't be going around minting new strings but str is perfectly fine for stuff like substring operations or comparisons.
Yes, of course. Rust has some new concepts that will be confusing at first, regardless of your background. You still have to understand Rust's destructors to understand that example. I didn't mean to say that it is impossible for Rubyists to learn Rust, or that C++ devs would understand Rust immediately.
Perhaps a better example:
fn foo() -> &usize {
let x = 50;
&x
}Yes, but is it more readable too? The obfuscated C contest also tends to produce a lot of dense/terse code, but you probably wouldn't want to use that in a production system...
Of course, you can write hard to read code. But that's not typically what comes out of a process of writing production software.
That's not to say that someone with no experience will fully understand the ownership transfer & borrowing that's happening, but that's just stuff you need to do for the compiler. Reading code that already compiles, you can mostly ignore that and focus on the program logic.
Especially for someone unfamiliar with rust, it can be hard to really know why someone is using self, &self, or &mut self. Yet the code reads the same.
That's the funny thing about rust.
v1, ok1 := <-c1
Not sure what is difference between := and = and what is that arrow. But if I'm going to do something with the language - I guess it will be easy to find out. Like with Rust.
The major exception to this are cases where authors use macros to invent their own DSL inside Rust code. This sort of thing seems common in the Servo codebase, amomg others. It reminds me of C macros or Python metaprogramming magic, both of which directly led to some incredibly difficult past debugging experiences.
The density comes from being able to share common functionality behind generic interfaces, so I don’t have to reinvent the wheel for every new project.
I find that most projects I make look the same internally, unless I start pulling some “clever” optimizations like custom allocators or self-referential structs.
Async rust is very messy and a pretty big issue atm. The tooling on the IDE side is subpar compared to Go.
To use? Eh - I just turn on async_std with the Tokio flag and write go-like code with async tasks. No issues thus far.
There are some pain points with cancellation in Rust. Dropping a future cancels it, but that requires ownership over the future, and may cause unexpected behavior due to the nature of futures state machines. This, along with many other issues, is being discussed by the async working group: https://github.com/rust-lang/wg-async-foundations/issues/65. If you have specific suggestions, or a problem that you faced, please open an issue! It is really appreciated - async rust's problems cannot be solved without community feedback and engagement.
It's not like JavaScript or Go where everything is just built into the language afaik.
Personally, I’m looking forward to the next few years when more and more companies reveal what patterns they use with Rust development. I think Rust is missing the kind of boost that Rails gave Ruby, for example, or that TypeScript and React gave Node/SSR. Or that Pandas gave Python.
1. https://doc.rust-lang.org/cargo/reference/specifying-depende...
2. https://doc.rust-lang.org/cargo/reference/features.html#depe...
I won't try to play as a Go devil advocate, because I don't feel good enough today to start such discussion.
What is the worst thing I have experienced in Rust? Lack of good packages, especially if we speak about cloud stuff (rusoto and google-api-rs). Human resources put from cloud providers are very scarce. As longer I dived into the Rust the more I felt I am alone freak, because I had to work more hours to achieve the same result as in Go, PHP, Kotlin, TypeScript, C#. My use case of Rust was a GraphQL gateway (gRPC+HTTP) and after few weeks of idea verification the project was dropped. Mostly because instead of developing business logic the team was focused to implement own libraries for Google Cloud and other SaaS offerings on their own. Ridiculous, but Mozilla devs [0] went the same way by taking the whole job on their shoulders and they were generating subsets of APIs, because they cannot find any good, official libraries. It is frustrating and time consuming making Rust completely no-go for many teams.
> I've worked a decent amount with Go, but I'm also frustrated with the size of projects balloon. When I compare my Rust and Go code, the Rust code ends up being much smaller (LoC) and much more dense/terse.
I can exactly the same about the Rust. I think it was not the problem with tool but with something between chair and keyboard. I had a pleasure to see and refactor very bad Go code and actual ballooning was never a case if you have applied Clean / Solid architecture. The "ballooning" was actual something nice, because anyone in the team could pick the repository and take care of implementing new business logic.
The number of lines of code is quite bad metric for Golang, because famous "if err != nil" takes a nasty 3 lines, while in many languages you can write it using single liner. In my humble experience, the number of lines of most Go web apps can be often compared to TypeScript apps. Also many web apps that I have developed usually had hefty 2-5k LoC and it is not bad result if we consider C# or Java web apps.
> - Powerful hygienic and non-hygienic macros
Yeah, having marcros in Rust is a gem.
> - Builtin benchmarking
Same as in Go. See testing.B.
It is weird you have pointed out
> - Builtin documentation
Same as in Go. See godoc.
> - FFI with Swift, C, C++, Node, etc to share code everywhere.
I rarely see the case for FFI in web app - I don't imagine even using it like that. It was common case for chart, TeX document or other web to image rendering to embed some library. I think it is a bad approach and the best currently is just run that code as separate binary, because it helps in maintainability of a third party dependency and your devops teams will love that decision.
As a person who rewrote the rxi/lite [1] to Rust I can only say I am terrified how many times I had to sacrifice having unsafe calls to just use some C code in my Rust application.
> - Crates.io is like NPM - really discoverable and easy to upload (with its goods and bads)
Personally, I feel Go/Deno/Docker flow of the installing dependencies is more convenient. I don't project names that do not sound what they provide. Naming thing is bad and I often see many developers are scratching head to find some unique name, so it could be easier findable in NPM or other repository. They are wasting time at looking for something short and funny and not something that is easily discoverable.
For many years, my only way of looking for dependency is GitHub. It helps to verify and investigate the quality of the code before adopting it in the application. It sometimes also results in contributing back to the project, because I already know where the project is located.
> - Really good project management through modules/Cargo.toml
It is really complex I'd say. But Cargo.rs would be nice to have :P
> - Generics make Map/Reduce/Filter really easy and readable
Matter of time in Go. :)
> - Serde is fantastic at automatically serializing/deserializing datastructures
Oh, that's true. Go has numerous serializers (for only JSON there are about 20+ nice looking implementations) and it is still interesting to see new ones, especially because they bring many non-obvious optimizations. Kotlin serializer is also top notch thingy. I recommend to use protobufs types in Go - even for domain models. It is interesting how with Go2 can improve the situation.
> - Very pleasant logging and tracing
The log package is nice, together with macro log! is really pleasant to look at it how concise it is to fill some context parameters around the message. I think it is like Logrus in Go, except the syntax it has the same features. There is also Zap package that sacrifices readability for performance. There is no problem to embed number of line of code, calling function in Go logs either.
Tracing? Yep, it feels the same for both languages I think. I had used OpenTracing (Jaeger) and I hardly can say I miss something from one or other language. Maybe some macro/annotation wrapper that will be added on compile time? However, I rarely see any use case right now for complicating such thing like tracing.
> - Like, really really good error handling, esp compared to Go
Hey, it is not that bad! :D But well, as long as you use Goland you don't care about the if-err-non-nil.
If you switch for few days to Java-world you will be like in hell after developing in Go, because the error-over-exception flow is really helpful to provide code that does not have any kind of error and you, as a developer, can guess what happens in specific line without any println("1") or debugger. Monads are nice but I will not trade current if-err for them.
> - builtin testing framework
AFAIK all modern programming languages includes some testing framework: Kotlin (kotlin.test), Zig (std.test), Elixir (ExUnit) etc. I am glad both Rust and Go joined that club.
> If you're looking into using Rust for web, I recommend https://github.com/http-rs/tide - it's the most pleasant web framework I've ever used.
It is interesting, but I think even today there is nothing that I could label as a "framework" in Go world. You wisely choose the best packages matching your needs. The situation has improved with many libraries providing a GraphQL endpoint.
> I've worked a decent amount with Go
Reading your post, made me think you don't have good Go experience and it sounded bad IMHO. I guess you had nobody proficient enough in production-ready Go apps to evangelize it within the team or there was no reason to use Go (yep, it is not a perfect tool). ;)
Rust shares many of the benefits of Go:
- statically linked binaries for ease of deployment
- good concurrency
- builtin testing framework
But it's a much sharper tool than Go:
- Really great error handling with Result/Option and the ? marker
- Like, really really good error handling, esp compared to Go
- Very pleasant logging and tracing
- Serde is fantastic at automatically serializing/deserializing datastructures
- Generics make Map/Reduce/Filter really easy and readable
- Really good project management through modules/Cargo.toml
- Crates.io is like NPM - really discoverable and easy to upload (with its goods and bads)
- FFI with Swift, C, C++, Node, etc to share code everywhere
- Builtin documentation
- Builtin benchmarking
- Powerful hygienic and non-hygienic macros
There's a lot more. I would say people choose Rust over other web frameworks not because of the language, but the emphasis on great tooling. Being able to test, document, benchmark, deploy, package, with a language that feels like a child between Go, JavaScript, and C++ is very attractive. Plus, it's fast - like really fast - and it's really obvious where optimizations can be made when the time comes.
I've worked a decent amount with Go, but I'm also frustrated with the size of projects balloon. When I compare my Rust and Go code, the Rust code ends up being much smaller (LoC) and much more dense/terse.
I've been working with it for a few years now, and I'm 100% willing to trade some complexity when doing Advanced Stuff (tm) for the 1st-class tooling. I hate having to decide which testing/documentation/building/benchmark/etc framework to use in other languages. I just want to build, not futz around with Jest/Babel/Webpack/Poetry/PyEnv/Opam/CMAKE etc.
If you're looking into using Rust for web, I recommend https://github.com/http-rs/tide - it's the most pleasant web framework I've ever used.