Live data from Hacker News

Thoughts on Go vs. Rust vs. Zig

sinclairtarget.com

81–90 of 599 posts

Re: Thoughts on Go vs. Rust vs. Zig

#81

Earlier quoted context omitted.

so does the rust compiler check for race conditions between threads at compile time? if so then i can see the allure of rust over c, some of those sync issues are devilish. and what about situations where you might have two variables closely related that need to be locked as a pair whenever accessed.

It entirely prevents race conditions due to the borrow checker and safe constructs like Mutexes. Logical race conditions and deadlocks can still happen.

Rust's specific claims are that safe Rust is free from data races, but not free from general race conditions, including deadlocks.

Re: Thoughts on Go vs. Rust vs. Zig

#82

Fine, but there's a noticeable asymmetry in how the three languages get treated. Go gets dinged for hiding memory details from you. Rust gets dinged for making mutable globals hard and for conceptual density (with a maximally intimidating Pin quote to drive it home). But when Zig has the equivalent warts they're reframed as virtues or glossed over. Mutable globals are easy in Zig (presented as freedom, not as "you ca…

I pretty new to Rust and I’m wondering why global mutables are hard? At first glance you can just use static variable of a type supporting interior mutability - RefCell, Mutex, etc…

> I pretty new to Rust and I’m wondering why global mutables are hard?

They're not.

  fn main() {
      unsafe {
          COUNTER += 1;
          println!("COUNTER = {}", COUNTER);
      }
  
      unsafe {
          COUNTER += 10;
          println!("COUNTER = {}", COUNTER);
      }
  }
Global mutable variables are as easy in Rust as in any other language. Unlike other languages, Rust also provides better things that you can use instead.

Re: Thoughts on Go vs. Rust vs. Zig

#83

Earlier quoted context omitted.

That seems like an odd characterization of Rust. The borrow checker and all the other type safety features, as well as features like send/sync are all about not giving you rope to hang yourself with.

The rope in my example is complexity. Ie choosing to use "all teh features" when you don't need or perhaps even want to. Eg sometimes a simple clone is fine. Sometimes you don't need to opt for every generic and performance minded feature Rust offers - which are numerous. Though, i think my statement is missing something. I moved from Go to Rust because i found that Rust gave me better tooling to encapsulate and reus…

I would love to see a language that is to C what Rust is to C++. Something a more average human brain like mine can understand. Keep the no-gc memory safety things, but simplify everything else a thousand times.

Not saying that should replace Rust. Both could exist side by side like C and C++.

Re: Thoughts on Go vs. Rust vs. Zig

#84

> Other features common in modern languages, like tagged unions or syntactic sugar for error-handling, have not been added to Go. > It seems the Go development team has a high bar for adding features to the language. The end result is a language that forces you to write a lot of boilerplate code to implement logic that could be more succinctly expressed in another language. Being able to implement logic more succinct…

it's the other way around

Rust used to not have operator?, and then A LOT of complaints have been "we don't care, just let us pass errors up quickly"

"good luck debugging" just as easily happens simply by "if err!=nil return nil,err" boilerplate that's everywhere in Golang - but now it's annoying and takes up viewspace

Re: Thoughts on Go vs. Rust vs. Zig

#85

Earlier quoted context omitted.

You can just as easily add context to the first example or skip the wrapping in the second.

I don't agree. There isn't a standard convention for wrapping errors in Rust, like there is in Go with fmt.Errorf -- largely because ? is so widely-used (precisely because it is so easy to reach for). The proof is in the pudding, though. In my experience, working across Go codebases in open source and in multiple closed-source organizations, errors are nearly universally wrapped and handled appropriately. The same is…

My experience aligns with this, although I often find the error being used for non-errors which is somewhat of an overcorrection, i.e. db drivers returning “NoRows” errors when no rows is a perfectly acceptable result of a query.

It’s odd that the .unwrap() hack caused a huge outage at Cloudflare, and my first reaction was “that couldn’t happen in Go haha” but… it definitely could, because you can just ignore returned values.

But for some reason most people don’t. It’s like the syntax conveys its intent clearly: Handle your damn errors.

Re: Thoughts on Go vs. Rust vs. Zig

#86
post #55

Good write up, I like where you're going with this. Your article reads like a recent graduate who's full of excitement and passion for the wonderful world of programming, and just coming into the real world for the first time. For Go, I wouldn't say that the choice to avoid generics was either intentional or minimalist by nature. From what I recall, they were just struggling for a long time with a difficult decision,…

> For Go, I wouldn't say that the choice to avoid generics was either intentional or minimalist by nature. From what I recall, they were just struggling for a long time with a difficult decision, which trade-offs to make. Indeed, in 2009 Russ Cox laid out clearly the problem they had [1], summed up thus: > The generic dilemma is this: do you want slow programmers, slow compilers and bloated binaries, or slow executio…

Ironically, the latest research by Google has now conclusively shown that Rust programmers aren't really any "slower" or less productive than Go programmers. That's especially true once you account for the entire software lifecycle, including production support and maintenance.

Re: Thoughts on Go vs. Rust vs. Zig

#87
post #29

> In Rust, creating a mutable global variable is so hard that there are long forum discussions on how to do it. In Zig, you can just create one, no problem. Well, no, creating a mutable global variable is trivial in Rust, it just requires either `unsafe` or using a smart pointer that provides synchronization. That's because Rust programs are re-entrant by default, because Rust provides compile-time thread-safety. If…

That seems unusual. I would assume trivial means the default approach works for most cases. Perhaps mutable global variables are not a common use case. Unsafe might make it easier, but it’s not obvious and probably undesired. I don’t know Rust, but I’ve heard pockets of unsafe code in a code base can make it hard to trust in Rust’s guarantees. The compromise feels like the language didn’t actually solve anything.

Re: Thoughts on Go vs. Rust vs. Zig

#88

> Other features common in modern languages, like tagged unions or syntactic sugar for error-handling, have not been added to Go. > It seems the Go development team has a high bar for adding features to the language. The end result is a language that forces you to write a lot of boilerplate code to implement logic that could be more succinctly expressed in another language. Being able to implement logic more succinct…

"Context" here is just a string. Debugging means grepping that string in the codebase, and praying that it's unique. You can only come up with so many unique messages along a stack. You are also not forced to add context. Hell, you can easily leave errors unhandled, without compiler errors nor warnings, which even linters won't pick up, due to the asinine variable syntax rules.

> Debugging means grepping that string in the codebase, and praying that it's unique.

This really isn't an issue in practice. The only case where an error wouldn't uniquely identify its call stack is if you were to use the exact same context string within the same function (and also your callees did the same). I've never encountered such a case.

> You are also not forced to add context

Yes, but in my experience Go devs do. Probably because they're having to go to the effort of typing `if err != nil` anyway, and frankly Go code with bare:

    if err != nil {
        return err
    }
sticks out like a sore thumb to any experienced Go dev.

> which even linters won't pick up, due to asinine variable syntax rules.

I have never encountered a case where errcheck failed to detect an unhandled error, but I'd be curious to hear an example.

Re: Thoughts on Go vs. Rust vs. Zig

#89

Generally a good writeup, but the article seems a bit confused about undefined behavior. > What is the dreaded UB? I think the best way to understand it is to remember that, for any running program, there are FATES WORSE THAN DEATH. If something goes wrong in your program, immediate termination is great actually! This has nothing to do with UB. UB is what it says on the tin, it's something for which no definition is…

Race conditions, silent bugs, etc. can occur as the result of the compiler mangling your code thanks to UB, but so can crashes and a myriad of other things. [...] That's it. That's all there is to UB.

You don’t think that’s pretty bad?

Re: Thoughts on Go vs. Rust vs. Zig

#90
post #4

For a lot of stuff what I really want is golang but with better generics and result/error/enum handling like rust.

I thought the recent error proposal was quite interesting even if it didn't go through: https://github.com/golang/go/issues/71528 My hope is they will see these repeated pain points and find something that fits the error/result/enum issues people have. (Generics will be harder, I think)

Didn't they say they're not accepting any new proposals for error handling?

I kinda got used to it eventually, but I'll never ever consider not having enums a good thing.

Post reply on HN