-
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: errors: configurable Handle(error) function #33162
Comments
One of the most common ways to handle an error is to return it. Am I correct in thinking that that is not supported here? It's very common for different functions to want to handle errors differently, but it seems that |
@ianlancetaylor thanks for taking the time to review this! As a clarification, returning an error does not handle it, it allows the parent function to handle it instead. This would not change that flow at all, it would only change the moments when errors are actually handled. You are correct that The point of this change is that the library code would use |
To clarify
There are many ways to handle an error and all are valid depending on the application. Here are some examples:
https://cloud.google.com/error-reporting/docs/setup/go
https://cloud.google.com/logging/docs/setup/go
This change means that library packages and all packages just call |
It seems to me that a library can let an application handle an error by simply returning the error. |
@ianlancetaylor thank you for taking time on this. This proposal is for instances when it impossible to
Since that was unclear I went back and edited the proposal to hopefully be more clear. Thanks again! |
It used to be very common to write programs that work by setting global values, rather than returning things. You could still do this today with: package globalerr
var Error error
func IsSet() bool {
return Error != nil
} And then just set this when you want to in your functions and methods. I don't think this is a good idea, however. This style of programming turns out to compose poorly and be quite brittle. I don't think there's any reason for the language to encourage this approach to errors. |
@carlmjohnson this isn't about having global errors. This is giving a way for packages to handle ones that are currently getting ignored. In the function ioutil.ReadFile there is an ignored error in
Although closing does not affect the flow of the program the error shouldn't be swallowed. I should know that errors are happening. This could be a memory leak in my program. Currently, if
Making a generic
The default for |
In my applications, my error handler function is very complicated and opinionated. It has multiple steps:
I would not want |
A much better example is
The
I believe that |
Based on the comments the proposal was unclear. I rewrote it to be more to the point. Thank you everyones for taking the time to review. |
I think we should decline all the error handling proposals until we are ready to revisit the topic (perhaps not for a few years). |
@rsc can you categorize this differently than all the other |
Moving to Go2 to be with all the other error handling proposals. |
@rsc this isn't a change like This is a fix for a missing feature of Go on how to make a decision on what to do with an error if it cannot be returned ( |
I appreciate that you feel strongly about this issue. I can't think of anything else in the Go standard library that works this way. The idea of a global handler just doesn't seem very Go like to me. This feature is only useful if the standard library itself uses it, but I think that for any specific case in the standard library we would look for some other way to return the error to the application. What I learn from your example of You suggest that shouldn't want to be opinionated, but in fact Go is an opinionated language, by choice. And the opinionated choice is to return errors. |
@ianlancetaylor Thanks for the kind words and taking the time to respond. That being said I disagree that
It would be amazing if the standard library used it, but it would be useful for any imported package. On the comment of
I agree that the Go choice is to return errors and I don't want to change that choice. Since Go has I went looking through a few lists of popular go library mostly searching for
Here are some other examples of how packages have chosen to handle errors were
|
@mvndaai, I think the issue you're pointing to is real, but I'm not sure a global error handler is a good solution. Different errors require different responses—log, ignore, panic (or abort, retry, fail if you remember the days of DOS)—and one handler can't be expected to tell which case is which. For deferred writes specifically, I and many other have a simple helper function. I think something like it should be considered for the standard library errors package. For problems with goroutines not reporting errors, I think a more systematic solution would be needed—possibly in an entirely new programming language. |
@carlmjohnson thanks for understanding that this is a real issue. Thanks for pointing out a way to handle deferred errors. Although that is helpful if people want to change how they are writing code and use named returns, that is still ignoring all I agree that different errors deserver different responses. I am not advocating that this be used instead of The issue is that are currently lots of places where errors cannot be returned. Imported packages, which I cannot control, have channels, The things in my control I can handle how I want. The ones that are not, have no standard way of being handled in go. They are usually a |
I'm using this code style to handle error: package main
import (
"fmt"
"src"
)
func main() {
if e := src.AddUser(); e != nil {
fmt.Println(e.Error())
return
}
} ./src/service.go package src
import (
"fmt"
"github.com/fwhezfwhez/errorx"
)
func AddUser() error {
if e := generateError(); e != nil {
return errorx.Wrap(e)
}
return nil
}
func generateError() error {
var e = fmt.Errorf("time out")
return errorx.Wrap(e)
} output:
|
@fwhezfwhez that package seems helpful, thanks for bringing it to my attention, but it does not solve a main issue of this proposal: What happens when a package you import has an error in a |
@mvndaai errorx aims to return errors trace-wrapped and handle them in an unified place.It doesn't conflict whether handle errors in func service() error {
defer func() {
if e:= destroyObject(); e!=nil {
handle(errorx.Wrap(e))
}
if e:= x.Close(); e!=nil {
handle(errorx.Wrap(e))
}
}()
e:= generateError("time out")
return errorx.Wrap(e)
} go func(){
if e:= service(); e!=nil {
handle(errorx.Wrap(e))
}
}() Apparently in |
@fwhezfwhez I am confused. I agree that you can call whatever |
It requires package itself provides xxx.SetErrorHandle(f func(error)) then you can handle error inner a package. |
@fwhezfwhez I would rather have an |
Thanks, but this is not a path that Go is going to take. I'm not denying that there is an issue here, but the specific idea of introducing a global handler is not the solution. Closing this issue. |
Problem
Most of the time in Go if an error occurs it can be returned. There are certain cases when this is not possible, usually
go
functions.Packages shouldn't choose how to handle errors so they end up either squashing the error or making configurable error logging like
ErrorLog
in httputil.ReverseProxy or http.Server.Proposal
I propose adding a function
errors.Handle(error)
that can be called in cases where it is impossible to return an error.There should be a second function
errors.SetHandler(func(error))
that can be called, usually inmain
, that lets an application choose how to handle an error. (i.e. log, increment a metrics, ...)The text was updated successfully, but these errors were encountered: