The same way you handle error return values in multi-threaded programs. Exceptions don't mean you simply ignore all errors all the time. They're just a different mechanism for communicating failures across function calls. You can code with exceptions the same way you do with errors.
Really the two styles of error communication are very similar. The default behavior for exceptions is to abort and let the parent deal with it, but you have the option of continuing on instead (catch). The default behavior for returned errors is to keep going, but you have the option of aborting and informing the caller. In either case you have to examine the code you're calling or its documentation to find out the details of what could happen when things go wrong.
Exceptions have the advantage of the abort-behavior requiring zero code, but it may be less obvious to beginners what is going on. In either case, people just don't like to be surprised, so they prefer what is familiar.
In C#, which has Tasks for concurrency (very similar to goroutines), an uncaught exception in a Task will bring down the entire program at some non-deterministic time, unless you make sure to observe it somewhere. So generally you're using some extension method so that invoking doSomething() in a Task looks like:
Really the two styles of error communication are very similar. The default behavior for exceptions is to abort and let the parent deal with it, but you have the option of continuing on instead (catch). The default behavior for returned errors is to keep going, but you have the option of aborting and informing the caller. In either case you have to examine the code you're calling or its documentation to find out the details of what could happen when things go wrong.
Exceptions have the advantage of the abort-behavior requiring zero code, but it may be less obvious to beginners what is going on. In either case, people just don't like to be surprised, so they prefer what is familiar.
In C#, which has Tasks for concurrency (very similar to goroutines), an uncaught exception in a Task will bring down the entire program at some non-deterministic time, unless you make sure to observe it somewhere. So generally you're using some extension method so that invoking doSomething() in a Task looks like:
Either that or you just make sure to catch anything at the root of your Task block.