I personally loved using Go 8 years ago. When I built a proof of concept for a new project in both Go and Rust, it became clear that Rust would provide the semantics I’m looking for out of the box. Less fighting with the garbage collector or rolling out my own memory management solution.
If I’m doing that with a lot of ugly code - I might as well use idiomatic Zig with arenas. This is exactly the point the author tried to make.
Your last paragraph captures the tension perfectly. Go just isn’t the tool we thought for some jobs, and maybe that’s okay. If you’re going to count nanoseconds or measure total allocations, it’s better to stick to a non-GC language. Or a third option can be to write your hot loops in one such language; and continue using Go for everything else. Problem solved.
> Or a third option can be to write your hot loops in one such language; and continue using Go for everything else. Problem solved.
Or use Go and write ugly code for those hot loops instead of introducing another language and build system. Then you can still enjoy nicety of GC in other parts of your code.
I can see that being an option in a small team that works closely with one another and wants to keep things simple.
Though it is my personal opinion that forcing a GC-based language to do a task best suited for manual memory management is like swimming against the tide. It’s doable but more challenging than it ought to be. I might even appreciate the challenge but the next person maintaining the code might not.
Go made it explicitly clear when it was released that it was designed to be a language that felt dynamically-typed, but with performance closer to statically-typed languages, for only the particular niche of developing network servers.
Which job that needs to be a network server, where a dynamically-typed language is a appropriate, does Go fall short on?
One thing that has changed in the meantime is that many actually dynamically-typed languages have also figured out how to perform more like a statically-typed language. That might prompt you to just use one of those dynamically-typed languages instead, but I'm not sure that gives any reason to see Go as being less than it was before. It still fulfills the expectation of having performance more like a statically-typed language.
By the common usage of the term, it is most definitely a systems language.
Systems are the "opposite" of scripts. Scripts are programs that perform a one-off task and then exit. Systems are programs that run indefinitely to respond to events. We have scripting languages and we have systems languages. While all languages can ultimately be used for both workloads, different feature-sets gear a language towards one or the other. Go is does not exhibit the traits you'd expect of a scripting language.
This idea that Go isn't a systems language seems to stem from "Rustacians" living in the same different world which confused sum types with enums, where they somehow dreamed up that systems are low-level programs such as kernels. To be fair, kernels are definitely systems. They run indefinitely too. But a user land server program that runs continuously to serve requests is also a system as the term has been normally used.
Long before Rust or Go existed, “systems languages” were commonly the ones you can write a whole system in to run on hardware, like C, Pascal or C++. I’m not opposed to that definition changing, but it certainly hadn’t when Go came out.
I agree that Rust enums should have been called unions, though.
While that does not match my memory, it works too. An assembly language is part of Go, so it fits among the languages you mention. The only constraint it imposes is your imagination (and what the hardware is capable of). However, it remains that "systems language" was caveated as being for network servers specifically. But no matter how you slice it, I think we can agree that Go isn't a scripting language, so it must be a systems language.
Rust does use enums under the hood in order to implement sum types, so the name as it is used within the language is perfectly valid. It's just not clear how that turned into nonsense like Go not having enums (which it does).
It says "more like", not "like". Javascript now performs more like a statically-typed language, as one example. That wasn't always the case. It used to be painfully slow — and was so when Go was created. The chasm between them has shrunk dramatically. A fast dynamically-typed language was a novel curiosity when Go was conceived. Which is why Go ended up with a limited type system instead of being truly dynamically-typed.
If I’m doing that with a lot of ugly code - I might as well use idiomatic Zig with arenas. This is exactly the point the author tried to make.
Your last paragraph captures the tension perfectly. Go just isn’t the tool we thought for some jobs, and maybe that’s okay. If you’re going to count nanoseconds or measure total allocations, it’s better to stick to a non-GC language. Or a third option can be to write your hot loops in one such language; and continue using Go for everything else. Problem solved.