For the original issue of GC pauses, a narrow change is to move problem data to non-pointer-carrying types, or the bigger hammer of manually managed slices of those types. The second helps with fragmentation too. Some workloads can be split into multiple processes as a direct way to have smaller heaps. If none of those options are enough then off-heap storage lets you do whatever you want.
I do have some complaints about Go, but one of the big ones has been fixed since I last wrote much Go code and it seems like a fine choice for a lot of applications.
Interestingly, Rust has quite good failed compilation speed. That's almost good enough. The usual Rust experience is that it's hard to get things to compile, and then they work the first time.
To other people's usage patterns though, I imagine the group of people who don't do much with the type system rely more on running a built binary to see if it worked, which means they'll pay the full compile/link time cost more often.
Or having Cranelift as default backend.
https://uptrace.dev/blog/golang-memory-arena
These are all tools. Java used to have this all the time, and we (ex-java programmer) had ways around this until the JVM improved.
There are some fine points to the O(heap size), for example it's clearly unnecessary for the GC to scan objects that do not themselves contain pointers, and work is somewhat proportional to the total number of objects. Combining numerous small objects into manually managed slices, coming up with ways to make the most numerous items pointer-free, etc.
I learned a bit about this when an analytics workload I had ended up with unacceptable pauses (I think over 1 second), Go's GC is more sophisticated now but I think in any GC runtime you have the same considerations to some degree. Some of the best writing at the time was by Gil Tene, one of the principal authors of the C4 concurrent collector at Azul Systems, starting point here:
https://groups.google.com/g/golang-dev/c/GvA0DaCI2BU/m/SmEel...
Yes but Rust has a lot more availability of libraries to do stuff as a result. Want to do anything ML or scientific? You at least have a route in Rust where you don’t with Go.
As for availability if CGO is ok, then calling C or C++ code from Go is not that hard. Also, there is always an option to just start C++ process if extra data copies are OK.