-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: fmt: add %V format (like %v, but with deeper pointer de-referencing) #28141
Comments
I would recommend to at least specify in the proposal:
|
Current fmt does already follow pointers but not past the first level because it is unclear what should happen in case of cycles? Depending on the answer it might also add alot of complexity to implement which might better be suitable for a different package. |
What should this code print? type T *T
var v T
v = &v
fmt.Printf("%V", v) |
The %v format derefences one level deep already. The %V format would just indicate a preference for deeper dereferencing. Signs of trouble such as too deep nesting or cycles can be easily detected and formatting could fall back to its %v behavior then. With that said here are answers to the questions above.
It could print as them as &(&T{}) or &(&(&T{}))
It should follow the example of the one-deep dereferencing for %v
It should detect a too deep (e.g. >= 5) nesting level and fall back to formatting as %v
Having it in the core would be nice already for logging, for matting of error messages and test results. |
You may want to update the proposal to include (and expand on) all these details. Otherwise, people will have to read the whole thread to understand what you are proposing. |
Good point. I updated the proposal accordingly. |
I personally like the idea of using Other considerations:
|
The
The
I like that idea, thanks! So it's time to update the proposal with the two points:
|
This is not strictly true. Other implementations of fmt.Formatter may be implementing %V. There are many ways the default printing might not satisfy one use case or another. |
I don't agree with the non-compatibility argument: A type with an existing fmt.Formatter would use it the same as before (like all other builtin runes, e.g.
prints
The Logging pointers is almost worthless in cloud deployments (i.e. multiple running instances that are restarted aplenty) whereas logging object values is really useful for analyzing problems across many runs.
Fair enough. Thanks for considering the proposal. |
The current %v formatting of values is extremely useful. It already dereferences pointers up to one level deep. For types with more nesting levels it prints pointers though. E.g.
i,j:=42,53; fmt.Printf("%#v\n", []interface{}{&i,&j})
prints
[]interface{}{(*int)(0xc4000120d8]), (*int)(040c00160f0)}
that shows the int-pointers to be different. In some cases it may be more useful to show the actual value though:
[]interface{}{&int{42}, &int{53}}
The proposal is to add a %V format to indicate a preference for the value. It would allow deeper de-referencing: Just follow pointers (up to a reasonable limit, e.g. 4...8) until the actual value is reached and format it like %v. If the nesting is too deep it should fall back to %v formatting directly.
Problems with de-referencing such as invalid pointers or pointers to unmanaged memory should be treated the same as in the de-referencing done in %v formatting.
Since the rune %V is not used yet the proposed change is backwards compatible.
The formatting modifiers + and # match their %v counterparts, but the Go-syntax representation may only be an approximation if there is no way to instantiate such value directly in Go. E.g.
i:=7; p:=&i; fmt.Printf("%#V",&p)
could print it as
&(int(&int(7)))
For deeper levels something like
&...(int(7))
may be more readable.
The text was updated successfully, but these errors were encountered: