Better than C? Sure. But not better than languages that provide sum types; some of which have been around since the 70s.
There are a lot of great languages that end up mostly academic because they lack whatever the magical balance of features, simplicity and usefulness it takes for a language get mind share.
I suspect Go might have hit the magical balance with channels, strong types, great build system, simple minimal syntax and language keywords, fairly opinionated best practices (and formatting) and static single file deploys.
Sum types can handle multiple return values seamlessly in a typesafe way as a special case, but are not limited to that because they may have different data shapes other than simple products, and callers can be checked to deal with each possible shape at each call site by the compiler.
On a side note, the same people who claim that sum types are "better" are never able to come up with a constructive proposal how sum types could be integrated into Go in an elegant way.
They are "better" in that they are, in fact, more constrained; only when the error case arises will there be any accessible error value; otherwise, the actual expected value will be found. Since go uses an ad hoc product type, you always get an error value and the return value, even if they are mutually exclusive most of the time.
Also, they are both ways to build larger types from smaller ones, and the way they go about doing it is rather obvious from their names, and thus the contrast.
> On a side note, the same people who claim that sum types are "better" are never able to come up with a constructive proposal how sum types could be integrated into Go in an elegant way.
Forgo the cutesy anonymous members for the massive benefits of sum types? For a team which prides itself for its ability to perform trade-offs, they sure were rigid in this stance.
But multiple return values are there for much more than returned result and error. You conflate that with the specific use of returning result and error, and based on that, you claim that sum types are better. That's a straw man par excellence.
I am not a language designer, but I have become interested in languages in the past couple of years. Sum types require some sort of generics implementation, which Go does not have. I think the design choices the authors made regarding the language have made adding generics that much harder, that now they are struggling to find the "Go way" of fitting them into the language.
Does panic provide the stack-trace?
If the panic isn't recovered it will print a stack trace, if it is recovered you can get a stack trace with runtime.Caller().
Go's panics are exceptions.
When you're writing reusable library code (and when you think about the scale of Google's codebase, they must have an insane amount of these libraries), it's important to make this distinction. There are some error conditions where you really just want to say "if this ever happens, just die, because there's nothing sane to be done", and Go provides panic() for these situations, similar to the error() function in your code above.
For situations where you do want to return a meaningful error to the client, I think Go's multiple return values provide a very good way to do it, far better than the overloading of NULL or -1 that you find in C and C++.