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: invoke String() / GoString() and Format() on unexported fields #18281

Closed
novas0x2a opened this issue Dec 11, 2016 · 2 comments
Closed

fmt: invoke String() / GoString() and Format() on unexported fields #18281

novas0x2a opened this issue Dec 11, 2016 · 2 comments

Comments

@novas0x2a
Copy link

@novas0x2a novas0x2a commented Dec 11, 2016

First, I'll say up front that this is a Feature Request.

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

go version go1.7.4 linux/amd64

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

linux/amd64

What did you do?

This is a model of the problem: https://play.golang.org/p/_JsORLfYwk
Basically, I have an Ugly object which is an implementation detail of a Pretty object; Pretty does not export the ugly field because it's purely an implementation detail, and other packages don't need to know.

In the real version of this, I implemented fmt.Formatter on Ugly, but for simplicity here I've implemented String() since it exhibits the same behavior. I implemented Formatter so that when Ugly objects are printed into logs, they provide sufficient information for debugging (instead of just unhelpful pointer spam).

What did you expect to see?

The String() version of Pretty.ugly to be printed.

What did you see instead?

The undebuggable pointer spam version of Pretty.ugly.

This has come up before (gonuts thread / #17409 / #16698 / 4b9490e) but here I'm actually requesting a direct method of accomplishing this. A few workarounds exist:

  1. You can implement fmt.Formatter on every type which holds an unexported field which implements fmt.Formatter and have your higher-level Formatter call the hidden one.
  2. You can optimize the above slightly with two copies of the type (as mentioned in the gonuts thread: https://play.golang.org/p/5wGsFY3Fpc)
  3. You can export every field which implements a useful String() or Format()

None of these workarounds are very satisfying, though. I understand why the problem exists (fmt, being a different package, can't see the full versions of the unexported fields) but it seems like this situation compromises the usefulness of Stringer, GoStringer, and Formatter- these interfaces are front-line debug tools, and having to choose between "debuggable log messages" and "only export the minimum" I'd generally choose the former every time.

Thanks!

@minux
Copy link
Member

@minux minux commented Dec 11, 2016

@robpike
Copy link
Contributor

@robpike robpike commented Dec 11, 2016

This would require too much low-level work to belong in the standard library to support a rare case. As @minux says, reach outside the core library for this one.

@robpike robpike closed this Dec 11, 2016
@golang golang locked and limited conversation to collaborators Dec 11, 2017
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
4 participants
You can’t perform that action at this time.