Object thing1;
try {
thing1 = doStuff();
} catch(SameException e) {
// handle error 1
}
try {
return doOtherStuff(thing1);
} catch(SameException e) {
// handle error 2
}
vs thing1, err := doStuff()
if err != nil {
// Handle error
}
thing2, err := doOtherStuff(thing1)
if err != nil {
// Handle error
}
return thing2
Happy path is flat. Control flow is obvious and simple. I have not much more to add.>People say this, but in practice any code search reveals that "if err != nil { return err }" is everywhere. I believe that many Go projects aspire to annotate all errors, but much fewer actually do.
https://github.com/search?l=Go&q=%22errors.Wrap%22&type=Code
>Ironically, the nice thing about exceptions, as well as Rust error chaining crates, is that they do this automatically, so in practice programs written in languages with those features tend to have better error diagnostics than Go programs do.
Rust is a different ball game. Rust does not try to be simple. It comes at its own costs. (I like Rust too.)
>Computers are better at doing things consistently than humans are.
These empty platitudes come up frequently when debating language decisions online. But, it's so meaningless in so many dimensions. I mean, we could also 'use the computer' by adding C macros on top of Go and use them to reduce repetitiveness, but I don't think many people will applaud you for it. Simply applying computer code to solve a problem does not constitute good design.
Go's proof is in the pudding. It's been extremely reliable for me in real world applications.