Background: I have been developing in Go for ~5 years, and Rust for probably less than 2 months.
- Both Go and Rust use bounds checking on arrays/slices (which means out-of-bounds accesses are not allowed).
- Go is garbage collected, so memory leaks cannot occur.
- Rust encourages an ownership/lifetime model, so memory leaks cannot occur.
- Go can still have data races between multiple concurrent threads. To catch them, you must use the race detector _at run time_. Note however that Go encourages communicating information over channels, and if idiomatic code is being written the chance of data races is next to none.
- Rust cannot have data races in most cases, as it's ownership/lifetime model allows for catching them _at compile-time_.
- Both of these assumptions are based on no external C or unsafe code being in the picture.
TL;DR: Very similar.
EDIT: I used the wrong terminology -- sorry. Instead of _memory leak_ I should have said _dangling pointers_ (memory leaks can occur in _any_ language, Go/Rust/Java/JS/etc).
> Go is garbage collected, so memory leaks cannot occur.
Well it depends on how you define memory leaks. Memory leaks can of course occur logically. Like say you create objects in a cache and never remove them. It is still a memory leak.
But at the level that you define the memory leak, it seems Rust can be just as good as Go because memory ownership is tracked by the compiler. One can say it is even better because of compile time checks and no need to have a GC @ runtime present.
If you're worried about memory leaks, an obvious downside of Rust is that it encourages reference counting over GC (more accurately: has no GC, but that might change in the future), and reference counting can leak via cycles.
However, in practice most values can be neither Rc nor Gc but single-owner, like unique_ptr in C++, which is easier to reason about than either.
Yes, it's important to note that Rust isn't 'refcounting but not GC,' but single ownership + borrowing over all else, and then using refcounting if you find yourself in a situation where you need multiple ownership.
GC doesn't preven all the memory leaks. En easy example is a stack class backeed by an array. If you need more members, you allocate a bigger array and copy members. (The GC takes care of the smaller old array).
So far so good. But You forget to allocate smaller array (and copy members) when you consume too much memory. So 1000000* push(something) followed by 1000000*pop() keeps plenty allocated memory not in usage.
(It's not as brutal as malloc() and forget the result but still pretty awfull situation in a large project.)
According to that definition of memory leak, I guess you can call anything that doesn't eagerly free memory for memory leak. And the term gets quite weak and vague in that case.
The issue with this code is not that it isn't eager enough. It deoesn't free the memory ever (for value of ever "till the whole stack is not freed, that can be the whole runtime of the program").
- Both Go and Rust use bounds checking on arrays/slices (which means out-of-bounds accesses are not allowed).
- Go is garbage collected, so memory leaks cannot occur.
- Rust encourages an ownership/lifetime model, so memory leaks cannot occur.
- Go can still have data races between multiple concurrent threads. To catch them, you must use the race detector _at run time_. Note however that Go encourages communicating information over channels, and if idiomatic code is being written the chance of data races is next to none.
- Rust cannot have data races in most cases, as it's ownership/lifetime model allows for catching them _at compile-time_.
- Both of these assumptions are based on no external C or unsafe code being in the picture.
TL;DR: Very similar.
EDIT: I used the wrong terminology -- sorry. Instead of _memory leak_ I should have said _dangling pointers_ (memory leaks can occur in _any_ language, Go/Rust/Java/JS/etc).