5 ms·
Interfaces don't help in this case. Say you have a package called net: var Error = ... func Get(url string) (result, error) { if ... { return Er
by fauigerzigerk 10y ago
Interfaces don't help in this case. Say you have a package called net:
var Error = ...
func Get(url string) (result, error) {
if ... {
return Error
}
}
Users of your package would do something like this
r, err := net.Get("http://example.com")
if err == net.Error {
//handle this particular error
}
What if you decide that there are in fact different types errors or you want to return an error code with each error? How would you do that?
- rakoo 10y agoYou should read Dave's presentation again. Asserting for a type is the wrong way to do it, your library should instead provide a helper for the specific parsing you want to do. So if you want to know if this error is temporary, you should have this, inside the net package: func IsTemporary(err error) bool { // specific parsing } Similarly, if you really want an error code: func ErrorCode(err error) int { // a type assertion, which is fine because we're inside the net package v, ok := err.(ErrorWithStatusCode) if ok { return v.ErrorCode } } (Note that in the standard net/http package, the result of an http call is inside the result, never in the error that is returned, whatever the status of the http call is) Basically your package should give all tools so that callers can take a decision without knowing about internals of the package. Knowing the exact error code is probably not what a caller wants; what they probably want to know is whether the error is temporary or fatal, if they can retry with a chance of success, if they can take counter-measures and if they can't alert the user.
- fauigerzigerk 10y agoI think I have read everything Dave Cheney has ever written about errors. But you misunderstand what I'm saying. The standard library is already littered with error values defined on the package level. Many third party packages emulate that approach. Once you have done that in package, there is no way to change it. You cannot add function call specific data to an error after the fact. There is no way to implement an IsTemporary(error) function once you have clients that compare any returned error to a package level singleton using ==. >Knowing the exact error code is probably not what a caller wants I had that need many times. For instance, I needed to get the SQLSTATE from database errors. There is a huge number of SQLSTATE codes and interpreting/classifying them can't be the job of a data access package or even a DBMS specific driver library. Also, how would a networking package know what I consider temporary? Some protocols like HTTP specify some errors to be temporary, but that may not coincide with what I'm willing to retry or not retry.
- zalmoxes 10y agoWhat you're describing with net.Error is a sentinel error. var Error = errors.New("your error string") You can also create a type or a struct that implements error. Example from stdlib: ``` // PathError records an error and the operation and file path that caused it. type PathError struct { Op string Path string Err error } func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() } ``` Dave Cheney's other blog post/talk goes into various ways to handle errors in Go here: http://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully http://dave.cheney.net/2016/04/27/dont-just-check-errors-han...
- fauigerzigerk 10y agoI know all the options I have and I have read everything Dave Cheney (and Rob Pike) has written on the subject. But to quote myself: "there is no way to add instance specific information to errors in a later version of a package". Once you have decided to use a package level error value (sentinel error as you say), there is no way to change that. As there is a huge number of such error values in the standard library and also a substantial number of other types of errors like PathError, "there is no general and reliable way to handle specific types of errors".
- uluyol 10y agoMethods can always be added. Yes the values and types can't be changed but we can extend the existing types to have these methods and give naked error values (errors.New) new types. It wouldn't be breaking the Go1 guarantee because they would still have the type error, only the underlying type would change.
- fauigerzigerk 10y agoAll true, I never said anything different. But what's the point of adding methods? What you can't do is add call specific information to errors returned from a particular function if that function returned a package level singleton value before.
- deleted 10y ago[deleted]