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 %v, %+v, %#v do not consider Stringer or GoStringer interfaces recursively #16698

Closed
ScottMansfield opened this issue Aug 15, 2016 · 2 comments

Comments

@ScottMansfield
Copy link

@ScottMansfield ScottMansfield commented Aug 15, 2016

Please answer these questions before submitting your issue. Thanks!

  1. What version of Go are you using (go version)?
$ go version
go version go1.6.3 darwin/amd64

I also checked tip.golang.org source to see if it had been changed. It hasn't.
https://tip.golang.org/src/fmt/print.go#L677

  1. What operating system and processor architecture are you using (go env)?
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/smansfield/gopkg"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.6.3/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.6.3/libexec/pkg/tool/darwin_amd64"
GO15VENDOREXPERIMENT="1"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common"
CXX="clang++"
CGO_ENABLED="1"
  1. What did you do?

This playground is the minimal example: https://play.golang.org/p/A9U4LteYyF

When creating an enum that is meant to be passed around in a larger struct, I wanted to create a human readable version of it. In this case, printing with any form of v doesn't do what I expect. The String() and GoString() methods are not considered when recurively printing the fields of a struct. This issue is stating that the Stringer and GoStringer interfaces should be checked in the printValue method and used if available.

https://tip.golang.org/src/fmt/print.go#L677

  1. What did you expect to see?
{foo}
main.containsEnum{field1:go type foo}
{field1:foo}
foo
go type foo
foo
  1. What did you see instead?
{0}
main.containsEnum{field1:0}
{field1:0}
foo
go type foo
foo
@martisch
Copy link
Contributor

@martisch martisch commented Aug 15, 2016

The field1 is unexported and needs to be exported by naming it Field1 otherwise fmt cant use the reflect package to "extract" the concrete value of field1 from the struct and user the Stringer and GoStringer interfaces.

type containsEnum struct {
    Field1 enumType
}

if you do not want to export field1 you can define String and GoString functions for the containsEnum struct since these have direct access to field1:

func (ce containsEnum) String() string {
    return ce.field1.String()
}

func (ce containsEnum) GoString() string {
    return ce.field1.GoString()
}
@minux
Copy link
Member

@minux minux commented Aug 15, 2016

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.