Meanwhile my experience with Go has been the reverse. I’ve found it acceptable for most use cases, but for network services it really stands out. Goroutines <3
Meanwhile my experience with Go has been the reverse. I’ve found it acceptable for most use cases, but for network services it really stands out. Goroutines <3
Goroutines don't have the restrictions of async that you must never block or spend too much time computing. Goroutines are preemptable. The language has memory-safe concurrency (except for maps, which is weird) and has garbage collection. So you can have parallelism without worrying too much about race conditions or leaks.
Go comes with very solid libraries for most server-side web things, because they're libraries Google uses internally. Rust crates have the usual open source problem - they get to 95%-99% debugged, but the unusual cases may not work right. Go has actual paid QA people.
Go has limited aims. It was created so that Google could write their internal server side stuff in something safer than C++ and faster than Python. It has a limited feature set. It's a practical tool.
I write hard stuff (a multi-thread metaverse viewer) in Rust, and easy web stuff (a data logger which updates a database) in Go. Use the right tool for the job.
Most of the time you can also avoid this by just copying data using .clone(). This adds a tiny bit of overhead, which is why it isn't a default - but it'll still be comparatively very efficient.
Similarly, there are facilities for shared mutation (Cell/RefCell) and for multiple owners extending the lifetime of a single piece of data (Rc/Arc). It's not that hard to assess where those might be needed, even in larger programs.
My understanding is you should operate the other way around. Things aren't safe for concurrent mutation unless it's explicitly documented as safe.
> So you can have parallelism without worrying too much about race conditions or leaks.
You might not worry, but I find these the two easiest classes of Go bug to find when entering new codebases ;).
Still, I agree Go is easier to get a web service up and running with.
Go's concurrency model is bog-standard shoot your foot off shared memory.
A channel is not magic, it's a multiple-producer multiple-consumer queue, you can unwittingly send a pointer over it (or a pointer-ish, like a hashmap) and boom you've got unchecked concurrent mutations, and in Go that even opens you up to data races (memory unsafety).
And because channels are slow, it's common to go down the stack, and hit further issues of mis-managing your mutexes or waitgroups, to say nothing of spawning a goroutine by closing over a mutable location.
You can do it right, in the same way you can do it right in C, C++, Java, Ruby, or Python. And arguably it's more difficult in Go because it drives you significantly more towards concurrency (and spawning tons of goroutines) without really giving you better tools to manage it (the only one I can think of is select).
thats hilarious, my daily driver language is elixir which is the goat for network services. I saw rust as the perfect compliment for that where I need everything else.