DEV Community

Cover image for I Tried Every Hot Programming Language
gohashira
gohashira

Posted on

I Tried Every Hot Programming Language

In this post, I'll make an attempt to compare GoLang, Zig, and Rust. And why Rust wins this comparison (for me).

Story Time!

I wrote 3 of my projects in GoLang, Zig & Rust. These projects are sufficiently big to get a good idea about the language fundamentals, shortcomings, and whether there's a problem with the language, the framework, or the ecosystem.

TIP: feel free to jump to TLDR section to just get the damn answer.

GoLang

I started building developer tools a few months back, initially with GoLang.

The first one was a basic database management & migrations utility (dbdaddy) and I genuinely had fun working with GoLang.

Even though this was my very first attempt with GoLang building something more serious than Advent Of Code & 1 billion row challenge problems, I was surprised that it took me less than a week to get proficient at it.

Zig

All this while, I was dabbling with Zig on the side (nothing too serious). I heard about Redis changing their license to a "technically non-open-source" license.

And I thought to myself: how hard can it be to build a new open-source redis in zig?

new redis jian yang meme

Fast-Forward 2 months later: damn.

The basic idea behind "GbCache" was an LRU-based in-memory cache but the actual source of truth was to be saved on disk along with features like notifications for specific key/value changes caused and obviously TTLs assigned to keys.

It is impressive how explicit Zig is, which makes it all the more simple and easier to work with.

I started GbCache from the perspective of "if it were to go HyperScale™ tomorrow, can it handle the load?"

This perspective drove me to rule out GoLang because if I am unable to reason with extreme certainty about the memory allocations, I won't have complete control over the speed.

Doing things from this perspective is a really great learning experience because suddenly you start seeing all the points in your program that might blow up, run out of memory or may become a bottleneck —the hot paths in your code.

Due to Zig's explicitness, I was sure of exactly where & when I am allocating memory.

But... Zig is NOT a memory-safe language at the end of the day and I am a guy with skill issues the size of Everest.

enters rust

In the last 2 years, I've tried and rage-quit on Rust 3 times. Coming from a JavaScript background where we have a bajillion gb ram in our macbook m69 maxes, I never really understood why Rust had those rules, and going in with the hype was probably a bad angle to look at it from.

Even though I rage-quit several times, Rust was still in the back of my mind, its weird syntax, frustrating memory rules, and mind-boggling lifetimes.

But something hit me while writing Zig... I already was keeping track of all these memory rules and lifetimes but as a mental overhead.

I started noticing patterns and boilerplate in my Zig code trying to do what Rust already does.

Rust

While building the CLI client for SFS (SFW name - "Simple File Storage") I decided to give Rust another try.

This time around while going through the rust book, I started to feel the "why" of it all.

The most fundamental thing that I love about Rust is the ownership & borrowing-based mental model of memory.

Even though this model of owned & referenced memory is imaginary, it is a convenient mental model to reason about and incurs less overhead over my head.

As opposed to the classic mental memory model that languages like C & Zig incur on your head. Have to track individual memory allocations & their lifetimes in my head? no thanks!

TLDR

GoLang

  • FAST (like your 5 MAUs are gonna need it lmao)
  • reliable
  • stupid simple, language is never standing between you & your goal
  • great ecosystem of packages

Zig

  • BLAZING FAST
  • stupid simple

Rust

  • BLAZING FAST
  • reliable
  • great ecosystem of packages

All Of Them

  • amazing error handling

If you're an everyday normal mo— backend engineer and like doing numbers on their sprint performance, your best choice is probably GoLang.

"but my company doesn't use GoLa—"
"leave the company, leave it, use the right job for the tool. leave the company."

To me, GoLang is like an arranged marriage where you never feel that rush in your heart but it never lets you down, it's your ride-or-die companion and you can bet your whole life on it.

But my friend if you are looking for that rush keep reading on!

Rust Puran

bu— but i want that rush... i want to feel my heart explode on catching a mere glance at their ey-syntax... i want to feel like i am in heaven when I'm with them and in hell when I'm not...

blue hair rust guy

Let's have a quick look at an example of multi-threaded safety in Rust.

use std::thread;

fn main() {
    let mut counter = Box::new(0); // 32-bit integer allocated on the heap
    let mut handles = vec![];

    for _ in 0..10 {
        let handle = thread::spawn(|| {
            *counter += 1; // trying to edit the value
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap(); // WAITING FOR ALL THE THREADS TO COMPLETE
    }

    println!("Result: {}", *counter);
}
Enter fullscreen mode Exit fullscreen mode

We have a heap-allocated value and there are 10 threads trying to modify it independently.

This code is unsafely accessing the counter variable as all the threads will try to modify counter simultaneously.

In other languages, similar code will happily compile and run.

If you have worked in a multithreaded environment before, your first thought might be to use a "mutex" to prevent race conditions in updating the counter variable.

But it's easy to miss little things like this in a big codebase due to human error.

Rust won't even let this program compile.

Due to ownership & borrowing rules, the compiler will detect that you are mutably borrowing counter in the first thread in the first iteration of the for loop... ok until now... the second iteration also wants to mutably borrow counter parallelly? unsafe! raise a COMPILE-TIME ERROR!!.

referencing or "borrowing" a value from its owner with the intention of mutating/modifying is called a "mutable borrow"

src/main.rs|8 col 36-38 error| cannot borrow `*counter` as mutable more than once at a time `*counter` was mutably borrowed here in the previous iteration of the loop
Enter fullscreen mode Exit fullscreen mode

In situations like these, other languages don't give you any error at all. It's your responsibility to inspect the correctness, Rust prevents that.

Constructs like these spread across the language help you to not shoot yourself in the foot (often).

Conclusion

IT DEPENDS!

I really wish there were a language that was the answer and even if GoLang comes pretty close to that, it really depends on your use case and most importantly, your team.

for me, Rust is a pleasure to work with (for now, who knows... hehe)

folks at TigerBeetle took a chance on Zig and they're happy with it.

Primeagen is happier with Zig.

for Jarred Sumner, Zig is fine, he wrote Bun in Zig.

Mitchell Hashimoto (guy behind HashiCorp) is writing ghostty in Zig, a BLAZING FAST termin—

.
.
.

wait...

Top comments (35)

Collapse
 
danielo515 profile image
Daniel Rodríguez Rivero

Not sure bro, I feel your list is missing Gleam

Collapse
 
gohashira profile image
gohashira

How was your experience with it? I’ve been procrastinating on trying it…

Collapse
 
dar5hak profile image
Darshak Parikh

I have tried building a small web app in Gleam + Lustre. While it shares the "minimal core" idea of Go, it makes a different set of tradeoffs. Some initial observations:

  • Patterns like the pipe operator, the use expression and Records are a pleasure to use.
  • Keeping your types and enums in a separate file and importing them can sometimes get tricky.
  • IIRC, you cannot make a function call in top-level code, it has to be inside another function. This was a bit limiting.
Collapse
 
danielo515 profile image
Daniel Rodríguez Rivero

I just wrote tutorial examples, I can't give you an opinion. That's why I wanted yours 😅

Thread Thread
 
gohashira profile image
gohashira • Edited

I don’t have one either😅

Collapse
 
ahsandev2019 profile image
ahsandev2019

I stopped learning rust after 1 month fcking learn haha 😂😂😂 i think gokag is enough for me

Collapse
 
gohashira profile image
gohashira

Golang is enough for most people hahaha

Collapse
 
davidchandra95 profile image
David Andrian Chandra

i always interest in Rust due to its performance and memory safety but can't stand the syntax man.. I mean, what is this || has thing to do with spawning a thread.

thread::spawn(|| {
            *counter += 1; // trying to edit the value
        });
Enter fullscreen mode Exit fullscreen mode
Collapse
 
gohashira profile image
gohashira

This is called a closure, think of it as a “callback function”. in this case after spawning the thread, this closure will run in that thread

Collapse
 
beto0607 profile image
Albanesi, Roberto Javier

Loved the article!
I started learning a bit of Zig yesterday, and I'm planning to give it s try to Rust in the future.

Do you have any suggestions on learning material?

Collapse
 
gohashira profile image
gohashira

So glad that you liked the article!

You can start by learning fundamentals like ownership model, basic syntax and module structure from the rust book, and grab a small CLI side-project to apply the newly learnt stuff, I’ve found this way to work the best.

Collapse
 
andreygermanov profile image
Andrey Germanov

This is what I used to learn Rust:

germanovdev.hashnode.dev/rust-lear...

Good luck!

Collapse
 
valeriavg profile image
Valeria

Great article! I think I’m sold on trying Zig out 😆

Collapse
 
gohashira profile image
gohashira

So glad to hear that! I was thinking nobody would get that haha

Collapse
 
kasir-barati profile image
Mohammad Jawad (Kasir) Barati

For me only JS + Python. Golang is still in the back of my mind, but never got a chance to give it a serious try though.

Collapse
 
gohashira profile image
gohashira

Why not give it a try this weekend?

Collapse
 
stephenshorton profile image
Stephen Horton

Golang is worth it my guy

Collapse
 
taikedz profile image
TaiKedz

(My use cases are making CLI tooling for automation and testing.)

I've had a stab at all three this year, tried Rust and whilst it looked cool initially, as you try to ramp up the project, it does feel like it gets in your way more often than not... I actually found it easier to track the memory with Zig than with Rust.

But Go feels like it has just that little bit more welcome abstraction that makes it not quite as fast as Rust and Zig, but definitely a serious speed demon contender...

I really want to settle in with Zig but.... Go is easier to get-going with and Zig is still likely to change quite a few things at syntactic level... so I'm pursuing Go at the moment, and will come back to Zig when it hits 1.0

And yeah, I'm giving up on Rust. Smarter people than me seem to be having issues wrapping their cerebelli around it and I'm not up for that pain 😳

Collapse
 
gohashira profile image
gohashira • Edited

I feel you man… and as I concluded above, a lot of people are happy working with zig even though it’s not “memory safe”

Your point about rust getting in way as you ramp up seems interesting, and maybe I’ll run into the same issue,

But for now, rust feels fine to me, who knows maybe I’ll switch to go or zig later, idk…

But hey! more you mess around more you find out right?!

Collapse
 
crenshinibon profile image
Dirk Porsche

What about Nim and Odin. Look both pretty nice.

Collapse
 
gohashira profile image
gohashira

I mean I have seen on them on twitch streams and YouTube but haven’t got around to trying them + OCaml yet…

Collapse
 
milnor profile image
Milnor

Enjoyed your article! It was refreshing that you stated your favorite in the second sentence, rather than telling the reader they had to read everything to find out.

Collapse
 
gohashira profile image
gohashira

Glad that you liked it!

Collapse
 
james_takahashi_286ac1676 profile image
James Takahashi

thanks for your post

Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more