Earlier quoted context omitted.
For the threading difference, do you mean that Rust needs 'normal' threads plus async/await support, but Go can just lean on its built in concurrency support for both cases? i.e. Go threads instead of explicit async style code.
Your sentence implies that Go green threads can do both of what 1:1 threading and async/await can, but it's more complex than that: there's a tradeoff between the simplicity (only one concurrency primitive) and the capability of the said primitive: - with it's M:N model, Go cannot really do FFI efficiently, while both 1:1 async/await have no problem with that in Rust. - goroutines are cooperatively scheduled, while O…
Small stacks (and M:N threading) are needed to efficiently implement tens of thousands of goroutines.
CGO is slow mostly because it needs to switch to a larger stack when calling a C function.
It's a trade-off.
A different Go implementation could make Goroutines map 1:1 to threads and have fast cgo calls at the expense of slow goroutines.
Rust is not exempt from those trade-offs. They chose fast FFI and smaller runtime. They paid with slow threads.
Async/await promises to be the best of both worlds but it comes at a cost of great complexity, both for the programmer and the implementor.
At the end of the day under the covers it's just threads that need to be managed in a complex and often invisible way plus a complex rewrite of your straightforward code into a mess of a state machine.
I can confidently say that learning to use goroutines took 10x less time than learning async/await in C#.
I understand goroutines better than I ever understood async/away.