-
Notifications
You must be signed in to change notification settings - Fork 17.6k
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: io: add WriteAll function #67921
Comments
Similar Issues
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.) |
Ah, so the proper name and issue would probably would be a Or, if we go with "but Writer docs clearly state that it's not allowed", then why not remove all the invariant checks from the standard library? |
This sounds like a checker that the |
I believe that any means like testing/linting will decrease the risk (if there is one), but they will not make people remove the checks nonetheless:
|
I'm not convinced since |
The difference here is outlined in the #9096:
A partial write should be an error. The reason I would propose a function like WriteAll/Full (the naming is just an example) is to avoid the situation where This means that checking for an error would be enough to see whether any actions are required. If err is |
On further thinking, I think this function will not change how people check the resulting So, from my perspective, there are two choices:
|
I had this single-error return value in the description. I think it's not the time to finalize on the exact API since the idea behind the function (enforcing the Writer invariant) is not accepted yet. |
If you are sceptical about Writer, then panic, no need to return, just give feedback to the developer
|
There are 10+ examples in stdlib only where we don't trust writer (grepping for
|
The logical extension of this would be that nearly every callsite like: n, err := w.Write(b) would end up being replaced by: n, err := io.WriteAll(w, b) without clear guidance on when you should do the latter over the former. The whole purpose of this helper is because incorrect You could imagine a build mode similar to |
If you do encounter a defective Writer, is it completely safe by checking ErrShortWrite? No. The return values are all accurate, and the defect is actually still there, which is why the data validation exists. |
@dsnet I would do that, yes; replacing most write calls just to keep the debates about whether checking
I would say: always if you're thinking about checking for
...then you don't need it. It's a good replacement for the cases where someone may want to check for it, but they don't know whether the case with
You check for
Instead of:
Whether The naming could also be adjusted, maybe it's |
Return n is some Write after the need to try again Write, if you only need to ensure that n is complete, there is no need to judge again err. io.WriteAll/Full will rewrite Write err logic undesirable |
I agree with ten-years-ago me from #9096:
Let's not do this. |
This proposal has been declined as infeasible. |
Proposal Details
The docs of the
io.Writer
guarantee that a proper implementation should return a non-nil error in case if it was a short writer (n < len(data)
):It's cool, but we don't trust this contract even in the stdlib. There are several examples to it, most types would check whether
n
is in valid range, etc.The possibility of a weird implementation returning an invalid combination of
n
anderr
encourages complicated solutions like:Instead of just:
There are multiple patterns like it, but overall people may resort to stuff that may even give more guarantees. The copy solution above relies on the implementation details; it never claims to be more reliable if there is a bad
io.WriterTo
implementation or whatever.Since we already have
io.ReadAll
, perhaps we can add aio.WriteAll
to have something that guarantees the behavior we want to enforce on ourio.Writer
s.An example implementation could look like this (just to illustrate the idea):
It doesn't guarantee the full write (because it could be complicated to achieve), but it does guarantee that no matter which implementation we're dealing with, the invariant described in
io.Writer
interface is intact: err is never nil if the write is "short".Some things to consider:
WriteFull
is a better namen int64
is redundant in this case, but it can still be useful to handle the error if it happensThe best part is that instead of trusting either
io.Copy
implementation details (does it callio.WriterTo?, does it somehow more reliable that a plain Write?) or
io.Writer` implementation, we can call a function that adds a contract enforcement layer without involving any measurable overhead.Since it's very likely to be rejected, I will not do an exhaustive research. But this is what I have found today:
I can invest more time into it if necessary.
The text was updated successfully, but these errors were encountered: