Skip to content
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: Printf not respecting String() method of elements of a struct #17409

Closed
musiphil opened this issue Oct 11, 2016 · 6 comments
Closed

fmt: Printf not respecting String() method of elements of a struct #17409

musiphil opened this issue Oct 11, 2016 · 6 comments

Comments

@musiphil
Copy link

@musiphil musiphil commented Oct 11, 2016

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go1.7

What operating system and processor architecture are you using (go env)?

play.golang.org

What did you do?

First reported in https://groups.google.com/d/topic/golang-nuts/Upiw-xxCJxQ/discussion

If an operand of fmt.Printf implements method String() string, fmt.Printf respects it and uses it.
But it doesn't if an operand is a struct that has such an element.

https://play.golang.org/p/QJC7Q9Kpch

What did you expect to see?

Int(73) Int(73) 73
&{Int(73)} &{elem:Int(73)} &main.Box{elem:73}
…

What did you see instead?

Int(73) Int(73) 73
&{73} &{elem:73} &main.Box{elem:73}
…

In the second line of the output, none of the format specifiers ("%v", "%+v", "%#v") calls the String() method of Int, in contrast to the first line.

@quentinmit quentinmit changed the title fmt.Printf not respecting String() method of elements of a struct fmt: Printf not respecting String() method of elements of a struct Oct 11, 2016
@quentinmit quentinmit added the NeedsFix label Oct 11, 2016
@quentinmit
Copy link
Contributor

@quentinmit quentinmit commented Oct 11, 2016

This only happens if the field is unexported. If it's exported, String is properly called:

https://play.golang.org/p/STKBOnEVrb

@quentinmit quentinmit added this to the Go1.8Maybe milestone Oct 12, 2016
@musiphil
Copy link
Author

@musiphil musiphil commented Oct 12, 2016

That was mentioned in the original "golang-nuts" thread quoted earlier.
But I don't see why the exported-ness of a field should affect whether String() is used or not to print that field.

@martisch
Copy link
Contributor

@martisch martisch commented Oct 13, 2016

works as expected.

reflect can not extract the concrete value of an unexported field and thereby fmt cant either to call the String method.
https://play.golang.org/p/JPUA_FHkov

related:
#8965

@martisch
Copy link
Contributor

@martisch martisch commented Oct 19, 2016

If there are no arguments against i think this can be closed.

That the String method of an unexported field can not be called in another package is normal behavior and fmt is another package. In general e.g. somestruct.someunexportedfield.String() is not directly callable in another package.

It is possible to define a String method on Box that has access to elem and then hands this over to fmt directly to allow for the unexported fields String method to be called:

func (b Box) String() string { return fmt.Sprintf("%s", b.elem) }

func (i Int) String() string { return fmt.Sprintf("Int(%d)", int(i)) }
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Oct 19, 2016

I wonder if we can document this in some way that makes sense.

@gopherbot
Copy link

@gopherbot gopherbot commented Oct 24, 2016

CL https://golang.org/cl/31817 mentions this issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.