Have you used coroutines and threads before? Goroutines are basically coroutines multiplexed on threads.
If you want to, you can even just think of them as super lightweight threads.
They are not like processes, they share the same address space.
> They are not like processes, they share the same address space.
Yes, but is worth remembering Go's (concurrency) motto:
Do not communicate by sharing memory; instead, share memory by communicating.
With channels you can send values, or pointers to the shared address space, so is much more efficient, or even channels (channels of channels are a very powerful and useful concept).
Most of the time, following this principle will make sense. It should be also said though that it's not always the right choice.
There are situations where using locks or atomic instructions is the better choice. But they nearly only come up in performance critical contexts.
It would be very nice to have some kind of compile-time enforceable ownership of data regarding channels and goroutines because debugging thread-safety issues is a pita.
I don't know how feasable it is to implement this though.
It is feasible if the language is carefully designed around it. Rust implements this through its uniqueness typing system. It is impossible to have two threads share mutable data.
They are not like processes, they share the same address space.