-
Notifications
You must be signed in to change notification settings - Fork 18k
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
fmt: %x verb interacts badly with types having a String method #21535
Comments
I've narrowed the issue down to the following: package main
import (
"fmt"
"syscall"
)
func main() {
fmt.Printf("syscall.Signal(19) %%0d %0d\n", syscall.Signal(19))
fmt.Printf("syscall.Signal(19) 0x%%0x 0x%0x\n", syscall.Signal(19))
} ...which gives the following ouput:
|
Fun fact: the strange
The "stopped (signal)" string is generated by the Here's a small reproducer:
output:
|
So it would appear that |
I'd say that it's not ignoring it. It's applying it, not on the variable itself, but on the output of the variable's Is it supposed to behave like this? I think it is. The doc says:
Since the format you are using ( |
I see. Seems like an Interesting combination of factors that leads to a break in POLA as far as the user is concerned. Thanks for explanation. |
I think the main point here is: should It's obvious that the current rules play nicely with It could make sense to remove Not for go1, obviously, but maybe something to keep in mind for go2. |
That would be my choice, however I don't have an appreciation for "Thinking in Go" (as Bruce Eckel might say) yet and therefore only have the assumptions brought from a background in C - i.e. thinking "hmm, storage type is a |
In general, I'd say that if the underlying type can be interpreted directly by the verb (e.g. %x), then it doesn't make sense to me to indirectly interpret the value by invoking any method ( |
Making %x/%X special vs other string verbs (and adding another edge case to fmt rules) does not seem to warrant breaking existing code with go2 for. A type can satisfy the Stringer interface to be able to effect the output of fmt, that is an option. If the types value should be printed directly the Stringer interface can be left unimplemented or the Formatter interface can be implemented for more fine grained control. If the types String method should not be used by fmt with %x or %X verbs the type can satisfy the Formatter interface and return another value depending on the verb. Removing calling the String method in fmt in its current form would break a large amount of go programs (probably all that use logging or custom error strings). fmt mostly knows how to interpret the values directly and can print the underlying structure with %#v. The default that simple string verbs and %v call the String method (if it exists) seems more useful as it usually provides human readable output by default. Otherwise:
would print something like {63393490800, 0, 0x177380} as the direct interpretation |
@martisch thanks for the feedback. Considering the scarce budget for changes an hypothetical go2 would have, it makes sense to use that budget for changes that will bring a clear benefit to the Go users, and are largely uncontroversial; the change proposed above clearly does not meet those requirements. If we're not going to keep this issue as a go2 reminder (and I'm okay with that), I guess we can close it. |
Based on the documentation
In the example I gave above, the type ( Fundamentally, in the example I gave above...
Which seems a little bit bonkers - the author of the If I can make an analogy to Python - this feels like
I'm not necessarily suggesting removing calling of
OK, but isn't that a bit non-sequitur? The use-case here is "print this integer type in hex format". I don't understand how Also (from the specification):
This is somewhat of a misleading statement. I appreciate this is probably a bit of a sticky one and I can understand not wanting to change something that might have many dependencies. I'm also very aware of holding a fairly ignorant and idealist "but why doesn't the logical thing work" viewpoint (where "logical" is loaded with presumptions based on having used an array of other languages that work differently). |
The valued passed to fmt is not of type uint32 but has type WaitStatus The call to fmt is fmt.Printf("%X\n", ws) -> "print this WaitStatus type in hex format" |
@ALTree If this is a proposal than i think it needs to be refined to be clearer what the problem is and what the concrete proposed change of behavior in fmt is. |
Yes, that is very true, however WaitStatus is "derived" (n.b. terminology here is probably way off) from a It feels like the summary of this ticket is "yeah, maybe the current implementation is a bit counter-intuitive in some cases, but changing it would be a huge pain, so let's not". |
I would hope that the problem is clear. I do not, however, have a complete proposal that might "fix" this. |
@martisch not really a proposal (not from me, at least) I was just thinking out loud about the possibility of making this less unintuitive. I agree it's probably not worth it. So as far as I'm concerned we can close this. |
No problem. Thanks all for considering this ticket and for the open discussion. |
In this case it's a little odd, but it is indeed working as intended. |
Environment
What version of Go are you using?
Does this issue reproduce with the latest release?
Unknown - the Go playground code example, doesn't reproduce the behaviour I see locally (on Linux AMD64) - probably because the underlying OS/arch on the Go playground is not the same as my machine and hence my hard-coded example value (
0x137f
) is completely meaningless.What operating system and processor architecture are you using?
What did you do?
Here's the code I'm using to print a stop signal in various formats:
This produces the following output (see syscall_linux.go):
What did you expect to see?
Given that the underlying type of
syscall.WaitStatus
isuint32
, I expect thatws.StopSignal()
anduint32(ws.StopSignal())
should both print identically.Expected:
What did you see instead?
The text was updated successfully, but these errors were encountered: