-
Notifications
You must be signed in to change notification settings - Fork 917
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
Use pointer receiver on pq.Error.Error() #1083
Conversation
The library returns *pq.Error and not pq.Error. By using a value receiver, the library was documenting that consumers should expect returned error values to contain pq.Error. While *pq.Error implements all methods on pq.Error, *pq.Error is not assignable to pq.Error and so you can't type assert an error value into pq.Error if it actually contains *pq.Error. In particular, this is a problem with errors.As. The following if condition will always return false. var pqe pq.Error if errors.As(err, &pqe) { // Never reached as *pq.Error is not assignable to pqe. ... }
Would this break any users who have an
|
No that should work fine as this change only modifies the method receiver, not whether a pointer is returned. The only thing this would break is if someone was creating pq.Error outside of this library and creating values not pointers. Their usage would break as pointer receivers implement the method for only the pointer type, not the value as well. I don't know why someone would be doing that but it is something to note. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for this change!
Hello! In an unfortunate case of Hyrum's Law, this broke an internal package my team maintains. This is a shortened version of the function that broke: func mapError(err error) error {
if err == nil {
return nil
} else {
switch v := err.(type) {
case pq.Error:
err = doThingWithErrPtr(&v)
case *pq.Error:
err = doThingWithErrPtr(v)
// other cases for other errors
}
}
// more code here that returns an error
} Granted, this is a weird piece of code in a codebase with some technical debt and weird things in it. Just wanted to post this here in case anyone else experienced it. We downgraded to the previous version as a quickfix. |
I'm confused, how could it have broken that, you were checking for both? |
Compilation fails with this error:
|
Ah, just remove the |
The library returns *pq.Error and not pq.Error.
By using a value receiver, the library was documenting that consumers
should expect returned error values to contain pq.Error.
While *pq.Error implements all methods on pq.Error, *pq.Error is not
assignable to pq.Error and so you can't type assert an error value into
pq.Error if it actually contains *pq.Error.
In particular, this is a problem with errors.As. The following if
condition will always return false.