-
Notifications
You must be signed in to change notification settings - Fork 699
Conversation
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.
Not condoning the adoption of this PR, just suggesting code design changes to match other code in the repo, and pointing out issues with how the test is written that will cause it to erroneously pass.
errors_test.go
Outdated
t.Errorf("test %d: got %#v, want %#v", i+1, got, tt.want) | ||
} | ||
|
||
return |
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.
return | |
continue |
Otherwise, we break out of the test after the first test, because definitively tt.want == nil
.
Also, as written, by contract of the code design, we should expect all the other table tests to fail after this change.
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.
You are right. I will rewrite it.
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.
Thank you for your comments
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.
More detailed review now that the essential functionality is good.
errors.go
Outdated
@@ -280,3 +280,36 @@ func Cause(err error) error { | |||
} | |||
return err | |||
} | |||
|
|||
// Stack returns the first stack trace of the errors, if possible. |
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.
Using the phrase “the first stack trace” is ambiguous, depending upon which direction you are orienting the Cause chain. If you look at it going down the Cause
chain, the most recent StackTrace is the first stack trace encountered, in which case the stack trace being returned by this function would be the last stack trace.
Meanwhile, from the context that you appear to be intending, you are saying that the bottom-most StackTrace, which is the earliest one attached, is the first, and therefore the last one would be the most-recently attached.
And now even I have reversed my original top/bottom distinction from the last code review, by reorienting the Cause
chain. And thus, the difficulty in writing good documentation that explains accurately the contract of behavior.
Please attempt to rework this documentation so that the functionality is unambiguous. Such as, “… returns the earliest/deepest StackTrace attached to any of the errors in the chain of Causes.” Potentially requiring an explanation of what a “Cause chain” is or even how it should be orient for the purpose of understanding the behavior of this function.
Basically, I should be able to read this documentation only, and know the essential functional/behavioral elements of this black box, without having to read the code in order to obtain definitions or context.
Also, this documentation does not indicate what it should return if it is not possible to find a StackTrace. This should be documented so that the user is fully aware of the contract. c.f. the documentation in Cause: If the error does not implement Cause, the original error will be returned. If the error is nil, nil will be returned without further investigation.
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.
Thank you so much for your patience. Your advice has been invaluable, and I have followed the suggest expect the last one. I don't know how to deal with this documentation. And I just wrote your words on it. So could you help to make it more clear?
errors.go
Outdated
// the errors in the chain of Causes. If the error does not implement | ||
// Cause, the original error will be returned. If the error is nil, | ||
// nil will be returned without further investigation. | ||
|
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.
The docstrings should not have a space between them an the function. I don’t know for sure this would break godoc, but convention suggest we strictly enforce it.
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.
OK. I'd remove it. Thank you.
|
||
// Stack returns the earliest/deepest StackTrace attached to any of | ||
// the errors in the chain of Causes. If the error does not implement | ||
// Cause, the original error will be returned. If the error is nil, |
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.
I think you mean "the stacktrace from the original error will be returned"?
@wangsai-silence Could you please take a look at the comments above? |
OK. I've done. Thank you for remind me about that. |
Oh I was just looking for something like this. @wangsai-silence @puellanivis what is left to be done for this PR? |
Nobody answered. I have used it in my project. |
🤷 I don’t have collaborator rights to the repo, so I cannot approve and merge. Also, I was going to leaving the approval/denial of the mere design up to other parties anyways. The branch is however now out-of-date with the base branch, and likely would end up with a merge conflict or something. Fortunately, the code works both inside of and outside of this package. So there is not much stopping anyone from replicating it. But, with proper |
FWIW, I proposed something like this back in 2016. While it wasn't outright rejected, I closed the issue because I agreed with Dave Cheney's cautious approach. Since then, I've written this functionality into practically every Go application I've written, and I don't mind doing that. In fact, I expect I would continue to do so, even if this PR is merged, because, as Dave predicted, I seem to want subtly different things in each app. And now with the advent of Go 1.13's new error handling, it's even less likely I would write an application to depend on this feature. I'd tend to prefer a version based on |
@flimzy ah, asking each package to implement their own version makes sense with that link. I don't understand what |
Two things:
stackErr := new(interface{ StackTrace() errors.StackTrace })
for errors.As(err, stackErr) {
err = stackErr
}
if stackErr != nil {
stack = stackErr.StackTrace()
} |
|
Possible. As I said, the code is back-of-napkin quality, untested. I don't think it affects the substance of what I was saying. |
You are correct, But I would additionally recommend against using
|
All good advice. Please don't get hung up on the minutiae of a throw-away coding example. I should have just left the trivial example as a mental exercise to avoid derailing the conversation. 🤦 |
I don’t think we derailed things. We ended up with a corrected version, that people can use. It’s the good-ol’ “say a wrong answer, and you will immediately get 50 other people to do the work of finding the correct answer for you.” |
For this issue #173