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: %#v doesn't print type name for built-in underlying types #24815

Open
willfaught opened this issue Apr 11, 2018 · 4 comments
Open

fmt: %#v doesn't print type name for built-in underlying types #24815

willfaught opened this issue Apr 11, 2018 · 4 comments

Comments

@willfaught
Copy link
Contributor

@willfaught willfaught commented Apr 11, 2018

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

go version go1.10.1 darwin/amd64

Does this issue reproduce with the latest release?

Yes.

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

GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/willfaught/Library/Caches/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/willfaught/Developer/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.10.1/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.10.1/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/_1/ggvd2t1x7hz_185crsb36zlr0000gp/T/go-build166135441=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

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

What did you expect to see?

(main.Chan)(0x1043a080) (main.Func)(0xd5960) main.Int(1) main.Map{1:1} main.Slice{1} main.Struct{X:1}

Note the main.Int(1) part.

What did you see instead?

(main.Chan)(0x1043a080) (main.Func)(0xd5960) 1 main.Map{1:1} main.Slice{1} main.Struct{X:1}

Note the 1 part.


The type name isn't shown for Int like it is for the composite types like Slice and Map. This can make it difficult to understand the values in a composite type whose nested type(s) is an interface. For example, if the below code prints []Syntax{"a", "b"}, the types of the slice values are ambiguous:

type Syntax interface{ syntax() }

type Comment string
type Identifier string

func (Comment) syntax(){}
func (Identifier) syntax(){}

func main() {
	var s []Syntax = ...
	fmt.Printf("%#v\n", s)
}

This seems to violate the point of the %#v format:

a Go-syntax representation of the value

func main() {
	var s []Syntax = []Syntax{"a", "b"}
	fmt.Printf("%#v\n", s)
}

because the "Go-syntax representation of the value" is invalid:

prog.go:16:28: cannot use "a" (type string) as type Syntax in array or slice literal:
	string does not implement Syntax (missing syntax method)
prog.go:16:33: cannot use "b" (type string) as type Syntax in array or slice literal:
	string does not implement Syntax (missing syntax method)

Maybe this can at least be changed for Go v2?

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Apr 11, 2018

I think there are two different issues here. One is that we don't print a type when printing a numeric or string value with %#v. I think that is working as intended. The other is that when using %#v to print a slice of an interface type, we still don't print the type when printing a numeric value even though the actual type implements the interface. That may be a bug.

CC @robpike

@willfaught
Copy link
Contributor Author

@willfaught willfaught commented Apr 12, 2018

Thanks for clarifying.

For the second case, I think it should apply outside slices as well. For example, interface{}(Comment("a")) should print as something like main.Comment("a"), whereas Comment("a") can print as just "a".

@dpinela
Copy link
Contributor

@dpinela dpinela commented Apr 12, 2018

@willfaught But Printf can't distinguish between these two cases, since all of its arguments after the format have static type interface{}. Your second example gets implicitly converted into the first.

@willfaught
Copy link
Contributor Author

@willfaught willfaught commented Apr 12, 2018

Good point.

Maybe it makes sense then to always print the type if it's a named built-in type. Otherwise, the "a" printed by

type T string
fmt.Printf("%#v", T("a"))

isn't syntax for a value with type T.

You can omit it if the type is part of the composite type, like []T{"a"}.

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

Successfully merging a pull request may close this issue.

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