5 ms·
> Despite the performance costs, having a GC at your disposal after using Rust for very long is quite liberating. For a while my internalized borrow checker wou
by eridius 12y ago
> Despite the performance costs, having a GC at your disposal after using Rust for very long is quite liberating. For a while my internalized borrow checker would throw red flags on me tossing around data indiscriminately, but I learned to ignore it as far as Go code goes. I was able to quickly share state via pointers without worrying about safety, which was quite useful.
I haven't gotten very far into the article yet, but this paragraph sent up a huge red flag for me. GC does not make the code safe. All it does is ensure that values don't get destroyed while they're still referenced. But you still run the risk of data races. If you're writing single-threaded code then this is fine (because single-threaded code doesn't have data-races), but the program being written here is a concurrent program.
Obviously you can write safe programs in this fashion. But you still have to think about safety. The difference is the compiler doesn't verify safety for you, which means you can write code fast without worrying about the compiler yelling at you, but your program may have race conditions in it.
Anecdotally, a few years ago when I was active with Go, a program of mine would segfault about once a month. It was a command-line utility that I ran maybe a few times a day. The segfault was so sporadic that I could never figure out what was going on. Then Go 1.1 introduced the data race detector. Using that, I was able to discover that the Go runtime was actually spinning up two goroutines when I thought it was only using one (servicing the stdout and stderr of a child process), and the one buffer object I was writing to turned out to be written to from two separate threads. This usually worked, but on that rare occasion it would lose the race and overrun the buffer. This is a bug that plagued me for half a year, and I'm really glad that the Go team created that data race detector because I never would have figured out what was going on without it. But it's a bug that simply cannot happen with Rust.
- Manishearth 12y agoI was focusing on single threaded safety really. I do know that data races can't be prevented by a GC, but having to only worry about data races and not the regular memory safety bugs was quite nice. <3 Go's race detector (also the deadlock debugging support). Used it quite often though I didn't hit it much. Agreed, none of this is a problem with Rust :)
- acqq 12y ago> Using that, I was able to discover that the Go runtime was actually spinning up two goroutines when I thought it was only using one (servicing the stdout and stderr of a child process), and the one buffer object I was writing to turned out to be written to from two separate threads Wait, does it mean that go makes your code running in more threads without you knowing? When can that happen? Sounds scary if true.
- eridius 12y agoIt means that there's nothing in the API that tells you whether the function might spawn a goroutine. It has to document it. I don't remember the precise details anymore, but my recollection is I was spawning a child process and passing Writers to use for stdout and stderr (looking at os.exec, I don't immediately see anything that matches my recollection, so I'm wondering if maybe I was using a different package). I expected that it would internally do something like select over stdout and stderr in one goroutine, therefore making it safe for me to pass the same buffer object for both (because I wanted to combine writes). But instead it was spawning 2 goroutines, not 1. And there was no evidence in the API that what I was doing was wrong, the only way to know was for the data race detector to flag it.