Java, C#, hell, even python are better designed languages than Go.
Enumerated Types > Checked Exceptions > Error values > Unchecked Exceptions.
The spectrum I'm ranking on is how much assistance the compiler gives me in ensuring I am aware of the error. Java has support for the second best option but culturally avoids it like the plague. Go has support for the third best option and culturally leans hard into it. C# and Python are ranked strictly at the bottom.
The preference in many language communities for an error handling path that encourages little awareness of the errors that can occur reeks of laziness to me. Laziness that I will, without a doubt, fall victim too without superhuman amounts of diligence on my part to avoid.
Any problem that requires superhuman diligence just screams out for a robot to handle in my experience. Java, C#, Python and a myriad of other languages fail hard here. Go gets a little better culturally by focusing on checkers that are built into the compiler toolchain with a default to running culturally as well as having type a signature for return values clearly indicate the error. But the gold standard for error handling has to go to any language that has enumerated types. Rust, ML variants such as OCaml or Haskell as common examples.
And golang has them in the form of panics and they suck in goroutines.
If I want to read a json file, I have to have a named variable for the file, one for the byte string, and finally one for the parsed object (the only thing I care about).
Then for each statement I have to check if an error happened and return it if it did.
Whereas in something like Haskell I could use a Maybe and compose the functions to only forward the value at each step if it was present. Then at the end I would have a Maybe with the final value, which I could then return to the caller.
Golang makes the most common thing to do as verbose as the least common thing.
Did you worked in Java? Did you worked with async and exceptions?