I would be surprised and saddened if `?` as described in the blog was added to go. Error wrapping is critical for operating a service and staying sane; an operator encouraging `if err != nil { return nil, err }` is a step backwards.
Consider this situation(it may sound familiar): you get paged at 4am for 500s from a service, check the logs, see 'file does not exist'. go doesn't attach stacktraces to errors by default. go doesn't enforce that you wrap errors with human context by default. How do you debug this? Pray you have metrics or extra logging enabled by log level that can give some degree of observability.
This error could have been 'opening config: file does not exist' or 'initializing storage: opening WAL: file does not exist' or even just decorated with a stacktrace. Any of those are immediately actionable.
Now, if go decided to make error wrapping a first class citizen with a fancy '?' operator, I'd be excited. However, I doubt that will happen because go is definitely not rust-like in its design.
First of all, it's important to recognize that the majority of error handling in Go today is actually `if err != nil { return err; }`. Take a look at Kubernetes if you don't believe me.
Second of all, nothing prevents `x ?= Foo();` from implicitly doing `if x,err := Foo(); err != nil { return fmt.Errorf("Error in abc.go:53: %w", err)}`
K8s is regularly regarded as a very poor example of idiomatic Go code, along with the AWS client libs.
Searching our prod code, "naked" if-err-return-err showed up in about 5% of error handling cases, the rest did something more (attempted a fallback, added context, logged something, metric maybe, etc).
I would love a syntactic sugar for 'if err == nil {Errors.Wrap(err, *What I was trying to do")}'. As a SRE, making each part of the stack explicit (or explicitly non-explicit) is invaluable for understanding debugging. I'm A-ok with some forms of error throwing, but they need to be clear and understood.
if err != nil {
return fmt.Errorf("What I was trying to do: %w")
}
That's the correct and standard way to do error wrapping in Go since Go 1.13[1]. There is also Dave Cheney's pkg/errors[2] which does define "errors.Wrap()", but that has been superseded by the native functionality in Go.
Would it not be easier if Go just provided a stack trace attached to the Error? How to cleanly do this in Go I don't know, I do however do this in embedded C++ and it works well. I agree without context, errors can be hard to track down when they come from functions that are called by many other functions.
I am not a fan of manually wrapping errors because it seems inferior to stack trace.
Also, I hate that Errors in Go are mostly just random strings, super hard at a high level to do anything intelligent.
Consider this situation(it may sound familiar): you get paged at 4am for 500s from a service, check the logs, see 'file does not exist'. go doesn't attach stacktraces to errors by default. go doesn't enforce that you wrap errors with human context by default. How do you debug this? Pray you have metrics or extra logging enabled by log level that can give some degree of observability.
This error could have been 'opening config: file does not exist' or 'initializing storage: opening WAL: file does not exist' or even just decorated with a stacktrace. Any of those are immediately actionable.
Now, if go decided to make error wrapping a first class citizen with a fancy '?' operator, I'd be excited. However, I doubt that will happen because go is definitely not rust-like in its design.