Here at trendig we try to stay in touch with the newest trends and technologies in our field.
My past projects were mostly written in GO, C#, TypeScript or Python and I wanted to invest some spare time to learn a new language, just to see what it has to offer and whether it might be a good fit for future projects.
I have been eyeing the language Rust for quite some time, but never got around to starting to play with it. Finally I took the chance and ported an old program I wrote in GO to get a good understanding about the language, the infrastructure around it and the ecosystem of standard and external libraries. The language also seemed to be stable and mature enough to trust writing future projects in it.
After reading through the current draft of ‘The Rust Programming Language’, I decided to port an old CLI program written in GO to Rust. It’s a media tool to decode NWA files, which are sound / music files used in a old game engine by Key, into WAV files. This small program is a suitable project to port, since it has many things that will test many aspects of a programing language:
Having a library and executable components.
Having a CLI interface.
Simple IO operation (reading / writing files).
Using low-level bit and byte operations with well defined data size and endianness.
Parallelization of the code.
Nothing fancy and quite simple, but it has many building blocks to test a new language on many aspects.
It took me around 5 days to port my old GO program to Rust without having any prior experience with the language. 30% of the time I debugged a problem with the io::BufReader I had, which was a result of me having wrong assumptions about the io::BufReader behavior.
In the end I successfully finished my little project and it ran correctly and even faster than my GO implementation (which isn’t really well optimized and the code base is quite old).
You can take a look at the final result over at Gitlab.
From a technical standpoint following points felt good about Rust:
Installing Rust and keeping it up to date with rustup is a great experience. I don’t like that many development tools need Rust nightly builds. GO had the same problem too, many years ago before it was stable. I hope that the need to do so will soon go away, since it only complicated developing with many developers and keeping the build process consistent over many systems.
Thanks to a lot of good experience with the go command in GO in the past, I found cargo to be a great tool.
Dependency management felt nice. I never had any problems in any of my GO projects with its loose dependency management (using the vendor folder and godep), but had many unpleasant experiences using NPM. Cargo seems to be a good tool between those two extremes.
The compiler rocks. Errors and warning messages are helpful and I never had the feeling to work against the compiler.
There is some nice syntactic sugar in some places. Especially the error handling convention using the Result enum and the ?-operator.
And these points felt weird:
I don’t like the way Rust structures its source code and test files. After coming from GO’s modules and _test.go file convention, the way Rust defines modules and tests felt very verbose (sic!) and complicated (mod.rs files and using ‘mod’ keyword). It’s still way better better than C / C++ though. In the end it’s only convention, so it didn’t bother me much later on.
Errors don’t have a call stack attached to them. Having written a lot of backend API code, where a call stack of an error inside the log really helps with fixing problems and bugs, I really like the idea of attaching a call stack to an error. GO has the same problem, but it’s mainly amended by using the pkg/errors module (which is kinda standard for all of my projects). After some search I couldn’t find a nice and easy-to-use drop-in replacement for this problem, so if you know a clever solution for this problem, please feel free to comment.
Lifetimes: They are weird. They challenge my brain and common sense so much, that I refuse to use references in my structs. Especially when you come from GO, their usage feels alien. I resorted to using generics and traits instead of lifetimes. Borrowing on the other hand felt nice and the compiler did a great job helping me with them.
The standard library is lacking in resources and felt inconsistent in some places. For example I needed to use external crates to get functionality for endian-sensitive reading of data, writing a CLI interface and enabling green-thread-like parallelization of my work. In the end this wasn’t really a problem, since the ecosystem around Rust provides good implementations for those problems, but the standard libraries included in a programing language like GO provide much more functionality out of the box. The biggest inconsistency I had was the need to use a &'a [u8] instead of a Vec<u8> when using a Reader on byte data. Vec<u8> provides a Trait for a Writer, but not for a Reader… I’m sure there are good reasons for doing so, but for me using the language for the first time it just felt inconsistent.
Defining errors felt verbose.
Macros everywhere. I haven’t had any good experience with them in the past. I hope Rust will show me otherwise.
Shadowing. I guess that it’s a nice-to-have, but I’m not keen to debug the nasty kind of bugs they can produce in the wild. Again, I hope that Rust will show me otherwise.
After finishing my project, I had the following impressions about the usability of Rust inside a corporate environment:
Onboarding new developers to Rust and a Rust project will take much longer than for example a GO-based project. Not having a GC, having a borrowing concept, statement and expressions, a match keyword, macros and generics makes Rust much more complicated than for example GO. It takes us three days of introduction to GO for a new developer, until they can contribute to the project with production-ready code. I guess onboarding a new developer to Rust will take between 6 and 10 days.
The ecosystem of Rust in the web server / backend environment seems not as mature and battle proven as its GO-based counterparts. This is just an initial guess, but after having looked at the currently available standard library and external crates for Rust in these fields, I need to do a small POC to gain more confidence in this area.
After having said all of this, I think that Rust is a nice language that fills definitely a nice niche. I haven’t used it yet for a backend-based project (like a REST API), but I feel that it will not dethrone established languages for that use case and especially GO in my use cases. But I hope to be able to use Rust in a future project nonetheless, since I want to test my assumptions and get some more experience in how well Rust is suited for the backend side of web operations.