> 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…
Python's f = open('foo.txt', 'w') is even more succinct, and the exception thrown on failure will not only contain the reason, but the filename and the whole backtrace to the line where the error occurred.
Thoughts on Go vs. Rust vs. Zig
281–290 of 599 posts
Re: Thoughts on Go vs. Rust vs. Zig
#282Earlier quoted context omitted.
I feel like this misses the biggest advantage of Result in rust. You must do something with it. Even if you want to ignore the error with unwrap() what you're really saying is "panic on errors". But in go you can just _err and never touch it. Also while not part of std::Result you can use things like anyhow or error_context to add context before returning if theres an error.
Any sane Go team will be running errcheck, so I think this is a moot point.
- https://github.com/kubernetes/kubernetes/pull/132799/files
- https://github.com/kubernetes/kubernetes/pull/80700/files
- https://github.com/kubernetes/kubernetes/pull/27793/files
- https://github.com/kubernetes/kubernetes/pull/110879/files
- https://github.com/moby/moby/pull/10321/files
- https://github.com/cockroachdb/cockroach/pull/74743/files
Do we have linters that catch these?
Re: Thoughts on Go vs. Rust vs. Zig
#283Earlier quoted context omitted.
Isn’t rust proffered up as a systems language? One that begged to be accepted into the Linux kernel? Don’t device drivers live in the Linux kernel tree? So, unsafe code is generally approved in device driver code? Why not just use C at that point?
I am quite certain that someone who has been on HN as long as you have is capable of understanding the difference between 0% compiler-enforced memory safety in a language with very weak type safety guarantees and 95%+ of code regions even in the worst case of low-level driver code that performs DMA with strong type safety guarantees.
https://chadaustin.me/2024/10/intrusive-linked-list-in-rust/
Re: Thoughts on Go vs. Rust vs. Zig
#284Earlier quoted context omitted.
> But from my own experience, UB just means "consult your compiler to see what it does here because this question is beyond our pay grade." People are taught it’s very bad because otherwise they do exactly this, which is the problem. What does your compiler do here may change from invocation to invocation, due to seemingly unrelated flags, small perturbations in unrelated code, or many other things. This approach enc…
> Code that invokes UB is incorrect, full stop. That's not true at all, who taught you that? Think of it like this, signed integer over/underflow is UB. All addition operations over ints are potentially invoking UB. int add (int a, int b) { return a + b; } So this is incorrect code by that metric, that's clearly absurd. Compilers explicitly provide you the means to disable optimizations in a granular way over undefin…
Potentially invoking and invoking are not the same.
Re: Thoughts on Go vs. Rust vs. Zig
#285> 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…
I also prefer Rust's enums and match statements for error handling, but think that their general-case "ergonomic" error handling patterns --- the "?" thing in particular --- actually make things worse. I was glad when Go killed the trial balloon for a similar error handling shorthand. The good Rust error handling is actually wordier than Go's.
Re: Thoughts on Go vs. Rust vs. Zig
#286Earlier quoted context omitted.
> Even if you do, you now have an effective comment that tells you where to look if you ever get suspicious behavior. By the time suspicious behavior happens, isn’t it kind of a critical inflection point? For example, the news about react and next that came out. Once the code is deployed, re-deploying (especially with a systems language that quite possibly lives on an air-gapped system with a lot of rigor about updat…
> might as well have used C, the dollar cost is the same. When your unsafe area is small, you put a LOT of thought/testing into those small blocks. You write SAFETY comments explaining WHY it is safe (as you start with the assumption there will be dragons there). You get lots of eyeballs on them, you use automated tools like miri to test them. So no, not even in the same stratosphere as "might as well have used C". Y…
https://github.com/rust-lang/rust/commit/71f5cfb21f3fd2f1740...
https://materialize.com/blog/rust-concurrency-bug-unbounded-...
Re: Thoughts on Go vs. Rust vs. Zig
#287The reason I really like Zig is because there's finally a language that makes it easy to gracefully handle memory exhaustion at the application level. No more praying that your program isn't unceremoniously killed just for asking for more memory - all allocations are assumed fallible and failures must be handled explicitly. Stack space is not treated like magic - the compiler can reason about its maximum size by exam…
> No more praying that your program isn't unceremoniously killed just for asking for more memory - all allocations are assumed fallible and failures must be handled explicitly. But for operating systems with overcommit, including Linux, you won't ever see the act of allocation fail, which is the whole point. All the language-level ceremony in the world won't save you.
You can impose limits per process/cgroup. In server environments it doesn't make sense to run off swap (the perf hit can be so large that everything times out and it's indistinguishable from being offline), so you can set limits proportional to physical RAM, and see processes OOM before the whole system needs to resort to OOMKiller. Processes that don't fork and don't do clever things with virtual mem don't overcommit much, and large-enough allocations can fail for real, at page mapping time, not when faulting.
Additionally, soft limits like https://lib.rs/cap make it possible to reliably observe OOM in Rust on every OS. This is very useful for limiting memory usage of a process before it becomes a system-wide problem, and a good extra defense in case some unreasonably large allocation sneaks past application-specific limits.
These "impossible" things happen regularly in the services I worked on. The hardest part about handling them has been Rust's libstd sabotaging it and giving up before even trying. Handling of OOM works well enough to be useful where Rust's libstd doesn't get in the way.
Rust is the problem here.
Re: Thoughts on Go vs. Rust vs. Zig
#288> 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…
What is the context that the Go code adds here? When File::create or os.Create fails the errors they return already contain the information what and why something failed. So what information does "failed to create file: " add?
Re: Thoughts on Go vs. Rust vs. Zig
#289> 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…
That isn't apples to apples. In Rust I could have done (assuming `anyhow::Error` or `Box ` return types, which are very typical): let mut file = File::create("foo.txt") .map_err(|e| format!("failed to create file: {e}")?; Rust having the subtle benefit here of guaranteeing at compile type that the parameter to the string is not omitted. In Go I could have done (and is just as typical to do): f, err := os.Create("file…
?
is too strong.The UX is terrible — the path of least resistance is that of laziness. You should be forced to provide an error message, i.e.
?("failed to create file: {e}")
should be the only valid form.In Go, for one reason or another, it's standard to provide error context; it's not typical at all to just return a bare `err` — it's frowned upon and unidiomatic.
Re: Thoughts on Go vs. Rust vs. Zig
#290Earlier quoted context omitted.
> The baseline floor of quality will be higher for a Rust program vs. a C program given equal development effort. Hmm, according to whom, exactly? > Second, the total possible footprint of entire classes of bugs is zero thanks to design features of Rust (the borrowck, sum types, data race prevention), except in a specifically delineated areas which often total zero in the vast majority of Rust programs. And yet someh…
> Hmm, according to whom, exactly? Well, Google for one. https://security.googleblog.com/2025/11/rust-in-android-move... > And yet somehow the internet went down because of a program written in rust that didn’t validate input. You're ignoring other factors (it wasn't just Cloudflare's rust code that led to the issue), but even setting that aside your framing is not accurate. The rust program went down because the pro…
Except it does. This also has to do with culture. In Rust, I get the impression that one can set it up as roughly two communities.
The first does not consider safety, security and correctness to be the responsibility of the language, instead they consider it their own responsibility. They merely appreciate it when the language helps with all that, and take precautions when the language hinders that. They try to be honest with themselves.
The second community is careless, might make various unfounded claims and actions that sometimes border on cultish and gang mob behavior and beliefs, and can for instance spew unwrap() all over codebases even when not appropriate for that kind of project, or claim that a Rust project is memory safe even when unsafe Rust is used all over the place with lots of basic bugs and UB-inducing bugs in it.
The second community is surprisingly large, and is severely detrimental to security, safety and correctness.