mirror of
https://github.com/golang/go.git
synced 2025-05-25 09:21:21 +00:00
fmt: print &map like &slice and &struct
It was inconsistent. Also test these better. Also document the default format for types. This wasn't written down. Fixes #8470. LGTM=iant R=golang-codereviews, iant CC=golang-codereviews https://golang.org/cl/154870043
This commit is contained in:
parent
668ea79283
commit
a0c5adc35c
@ -13,7 +13,7 @@
|
||||
The verbs:
|
||||
|
||||
General:
|
||||
%v the value in a default format.
|
||||
%v the value in a default format
|
||||
when printing structs, the plus flag (%+v) adds field names
|
||||
%#v a Go-syntax representation of the value
|
||||
%T a Go-syntax representation of the type of the value
|
||||
@ -51,6 +51,21 @@
|
||||
There is no 'u' flag. Integers are printed unsigned if they have unsigned type.
|
||||
Similarly, there is no need to specify the size of the operand (int8, int64).
|
||||
|
||||
The default format for %v is:
|
||||
bool: %t
|
||||
int, int8 etc.: %d
|
||||
uint, uint8 etc.: %d, %x if printed with %#v
|
||||
float32, complex64, etc: %g
|
||||
string: %s
|
||||
chan: %p
|
||||
pointer: %p
|
||||
For compound objects, the elements are printed using these rules, recursively,
|
||||
laid out like this:
|
||||
struct: {field0 field1 ...}
|
||||
array, slice: [elem0 elem1 ...]
|
||||
maps: map[key1:value1 key2:value2]
|
||||
pointer to above: &{}, &[], &map[]
|
||||
|
||||
Width is specified by an optional decimal number immediately following the verb.
|
||||
If absent, the width is whatever is necessary to represent the value.
|
||||
Precision is specified after the (optional) width by a period followed by a
|
||||
|
@ -965,11 +965,12 @@ func TestFlagParser(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStructPrinter(t *testing.T) {
|
||||
var s struct {
|
||||
type T struct {
|
||||
a string
|
||||
b string
|
||||
c int
|
||||
}
|
||||
var s T
|
||||
s.a = "abc"
|
||||
s.b = "def"
|
||||
s.c = 123
|
||||
@ -979,12 +980,35 @@ func TestStructPrinter(t *testing.T) {
|
||||
}{
|
||||
{"%v", "{abc def 123}"},
|
||||
{"%+v", "{a:abc b:def c:123}"},
|
||||
{"%#v", `fmt_test.T{a:"abc", b:"def", c:123}`},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
out := Sprintf(tt.fmt, s)
|
||||
if out != tt.out {
|
||||
t.Errorf("Sprintf(%q, &s) = %q, want %q", tt.fmt, out, tt.out)
|
||||
t.Errorf("Sprintf(%q, s) = %#q, want %#q", tt.fmt, out, tt.out)
|
||||
}
|
||||
// The same but with a pointer.
|
||||
out = Sprintf(tt.fmt, &s)
|
||||
if out != "&"+tt.out {
|
||||
t.Errorf("Sprintf(%q, &s) = %#q, want %#q", tt.fmt, out, "&"+tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlicePrinter(t *testing.T) {
|
||||
slice := []int{}
|
||||
s := Sprint(slice)
|
||||
if s != "[]" {
|
||||
t.Errorf("empty slice printed as %q not %q", s, "[]")
|
||||
}
|
||||
slice = []int{1, 2, 3}
|
||||
s = Sprint(slice)
|
||||
if s != "[1 2 3]" {
|
||||
t.Errorf("slice: got %q expected %q", s, "[1 2 3]")
|
||||
}
|
||||
s = Sprint(&slice)
|
||||
if s != "&[1 2 3]" {
|
||||
t.Errorf("&slice: got %q expected %q", s, "&[1 2 3]")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1014,6 +1038,12 @@ func TestMapPrinter(t *testing.T) {
|
||||
a := []string{"1:one", "2:two", "3:three"}
|
||||
presentInMap(Sprintf("%v", m1), a, t)
|
||||
presentInMap(Sprint(m1), a, t)
|
||||
// Pointer to map prints the same but with initial &.
|
||||
if !strings.HasPrefix(Sprint(&m1), "&") {
|
||||
t.Errorf("no initial & for address of map")
|
||||
}
|
||||
presentInMap(Sprintf("%v", &m1), a, t)
|
||||
presentInMap(Sprint(&m1), a, t)
|
||||
}
|
||||
|
||||
func TestEmptyMap(t *testing.T) {
|
||||
|
@ -994,6 +994,10 @@ BigSwitch:
|
||||
p.buf.WriteByte('&')
|
||||
p.printValue(a, verb, depth+1)
|
||||
break BigSwitch
|
||||
case reflect.Map:
|
||||
p.buf.WriteByte('&')
|
||||
p.printValue(a, verb, depth+1)
|
||||
break BigSwitch
|
||||
}
|
||||
}
|
||||
fallthrough
|
||||
|
Loading…
x
Reference in New Issue
Block a user