The critical difference is that processes are isolated, they don't share resources like goroutines do. This makes it possible to separate the error handling from the business logic.
When you open a file, a socket, allocate memory, borrow a database connection from a pool, etc. you don't need to write try/catch/finally, or defer() statements, or logging, or any kind of error handling like that - if your code crashes, the VM will take care of the cleanup (because it knows what resources are owned by your process) and the supervisor above your process will log the problem and restart the process if necessary.
This makes Erlang applications much safer by default, and the business logic is clearer and simpler because it's not mixed with error recovery code (the "if err != nil" every other line that Go is famous for). The error kernel (the part of the app that must be carefully written to ensure reliability) can be kept really small[1].
This comes at a cost in performance, because data must generally be copied between processes, whereas goroutines can send pointers directly to each other. But if you can afford it, it's _very_ nice. Besides the error handling this also enables crazy observability (you can connect to a running app and inspect processes[2], kill them, send them messages, jump between nodes in a cluster, etc.), live code reload, and a bunch of nice things like that.
[Process isolation also enables clustering, where processes running on different machines can talk to each other as if they were in the same OS process. The copying means it doesn't matter if the other process is remote or local.]
[1] https://medium.com/@jlouis666/error-kernels-9ad991200abd
[2] https://github.com/zhongwencool/observer_cli#demo