Additionally, combining them with the power of channels makes quick work of many tasks. Channels of course can be implemented in C++ too, but having the compiler take care of it for you with additional tools such as the race detector is very handy.
For a large set of problems, they are very nice to work with.
Then there is the ongoing work to add async/await patterns into C++20.
Notice how you can always have that answer when it comes to programming languages: you can do the same in. The point is that, the way it's made in go, is awfully handy.
go func () { }
and Task.Run(() => { })
With the benefit that on the latter example, the runtime allows me to customise how scheduling is done.These aspects are key to goroutines.
It seems like both languages are equally capable here, with C++ having more power and foot guns when required as usual.
C++ with PPL on Windows, would be
task<T> handle = create_task([] { /* ... */ });
And with standard C++ future<T> handle = std::async(std::launch::async, [] { /* ... */ });
In both cases, with C++20 it will be possible to co_await handle, which you can already play with on clang and VC++.This is probably exactly the same behavior as goroutines.
Goroutines and .net tasks allow a nice mix of CPU bound and IO bound code. While a goroutine/task is waiting for IO or something else to complete (timer in this example), the runtime will immediately use the hardware thread for some other task, without OS involved.