-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: Go 2: just return the error #56628
Comments
You can‘t beat that for simplicity. It does not feel right though to make err special here, given that it is just another return parameter with no formal significance. |
@andig thanks for voicing that concern. I guess there is a point of view that Go is just returning multiple values, and there is no reason to formalize the return of errors in any way. The point of view that I am representing is that the code is not actually trying to return multiple values. The code is trying to return a success or an error, exclusively. Some functions are exceptions to this general pattern, and those exceptions should not use this feature, but what is described here represents the majority of functions in some code bases. AFAICT this can only really only be generalized to actually adding a Result types to Go (or more generally a sum type), which would be an enormous challenge. This proposal describes the one reliable convention for using sum types in Go. The benefits of sum types are clear to anyone that has experience using them, but it is not actually clear that a Result type would produce easier to read code for this common pattern than what Go would have after this proposal. |
In Zig a function can just return an error (or a success). The result type is formalized with pub fn parseU64(buf: []const u8, radix: u8) !u64 { The The return type would ideally be a concrete error set as in Zig rather than erased into an |
An argument could even be made that standardizing the use of a result type for the usual case of value or error will signal to the client that a function that isn't using the result type might need some special handling. It may be too late for that benefit, though, since the standard library is filled with multi-return value-or-error functions already. Still, I'd personally really like to have functionality similar to the following available, though it would be dependent on #56462 or something similar: type Result[T ...any] struct {
v T
err error
}
// Just doing some bikeshedding...
func R[T ...any](v T, err error) Result[T] { /* Converts from an existing multi-return function. */ }
func Success[T ...any](v T) Result[T] { /* Straightforward. */ }
func Err[T ...any](err string) Result[T] { /* Equivalent to errors.New(). */ }
func (r Result[T]) Must() T { /* Panic if there's an error. */ }
func (r Result[T]) IgnoreErr() T { /* Just return the value. */ }
func (r Result[T]) Or(v T) T { /* Return v if the error wasn't nil. */ }
func (r Result[T]) Err() error { /* Return the error, whether or not it's nil. */ }
func (r Result[T]) Unwrap() (T, error) { /* Return everything. */ }
// Elsewhere:
package fmt
func Resultf[T ...any](format string, args ...interface{}) { /* ... */ } Unfortunately, the That would require such a major overhaul of the type system that it seems extremely infeasible to me to implement for use with a single feature. I think an actual result type is far more likely to happen at some point. |
I like the idea of the It's easy to come up with the return result and such an API but it is harder to explain how this will actually be better on the caller side than what exists today. Rust had to add |
Author background
Related proposals
Proposal
When returning an error, one may omit the rest of the return values.
This new form matches the intent that "I just want to return an error".
The new form is optimal to read, write, and diff for the purpose of returning an error.
This form is allowed if and only if the last return value satisfies the interface
error
.The value of the omitted return values will be the zero value of their type.
Motivation
The benefits to readability will be seen in every multi-valued error return statement, which is a significant amount of existing Go code.
I see Go programmers returning structs as pointers because
nil
is easier than hassling with putting empty structs at every return, so unfortunately the existing situation contributes to making the code messier outside just the return statement.Reading, writing, diffing
Orthogonality
This proposal could be viewed as an extension/specialization to the existing concept of a naked/bare error return.
Because of this, it may be best to use named return variables when they exist rather than only returning zero values.
This feature is specialized to errors. It is possible to attempt to generalize this feature to support using it to return any return result type that is uniquely typed. However, such a generalization is rarely useful outside of bare/naked returns and bare/naked returns are not used with high frequency in the Go community.
Compatibility
Old code will continue to compile on newer versions of Go.
New code will not compile on older versions of Go unless this feature is back-ported to older releases, or the new code is modified with automated tooling.
Costs
What is the cost of this proposal? (Every language change has a cost).
An additional rule to understand. Outside of the interaction with named results, this rule should be intuitive.
Would this change make Go easier or harder to learn, and why?
Some will argue this makes Go harder to learn because it is a new additional feature. I would argue it will make it much easier to learn Go because it will be significantly easier to read error return statements- that saved time will make it possible to spend more time learning Go.
How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
Most linters that use the Go analysis library could continue to work without change for most of their lints.
However, some lints focused on the specifics of returns would require changes. It will now be easier to perform autofixes or suggestions that add an error return- these no longer need to bother with zero values.
What is the compile time cost?
Probably none? In theory an integrated compiler could compile this (probably not noticeably) faster since there is less to parse and returns must be type-checked already.
However, the separation of compilation phases might mean the effect would be the opposite.
What is the run time cost?
None, in theory this might make some optimizations easier.
Can you describe a possible implementation?
No, but I imagine the machinery for this is probably somewhat in place already due to the existence of bare/naked returns.
Do you have a prototype? (This is not required.)
I have a library that panics (and recovers) an error. This achieves the same result of omitting zero values.
The text was updated successfully, but these errors were encountered: