Yea, but in those languages you have a garbage collector working in the background to clean up after you. You don’t always want to pay that cost. From time to time I work on an open source application that spends 60–70% of its time in garbage collection, at least on jobs at the extreme end of the size we can handle. I’m starting to think about ridiculous hacks like combining millions of moderately–sized objects into a giant arena. With no pointers into the arena (just indicies), I can eliminate a huge chunk of the time wasted scanning the heap over and over again. But at that point, why am I writing this in Go? My Rust prototype is very incomplete, but for the parts that are implemented it uses way less memory and completes a lot more quickly. And I haven’t done _any_ performance optimization or ridiculous hacks there yet.
Reference counting has completely different properties than other forms of automatic garbage collection. In particular, reference counting still requires some amount of ownership tracking, whereas this concept just doesn't exist (for memory resources) with tracing garbage collection.
This is particularly relevant for certain algorithm, such as atomic initialization, that get significantly more complex with in-line ownership tracking.
Also, because of Rust’s wonderful type system it will be fairly straight forward to replace the string keys in this code with interned strings instead. (The amount of strings we use for paths in a large repository is pretty astounding.) That might now be almost possible in Go, if I learn the new generics.
That’s true; the prototype uses Rc/Arc for things where I don’t yet know for sure how the ownership should really work out, and doubtless a fair amount of that will stay.