Yes, that part might benefit from more constraints. There was a HN thread which approached it from a different angle: remove `go x()` and instead enforce mandatory use of WaitGroup/ErrGroup (i.e. a block that spawns them is the same block reaps them, always). I might extrapolate a bit here. https://news.ycombinator.com/item?id=26509986
I think something way more radical than "C++ threads but with a built-in concurrent queue" is needed. If the default was to share nothing, and any shared memory had to be explicitly shared somehow, that would be a great step in the right direction. Maybe the compiler could even check that explicitly-shared variables are protected by a mutex; something like how Rust mutexes "own" the things they're protecting and you can't access the underlying object without having the lock.