g G // a struct field that GoStrings
}
+// A type with a String method with pointer receiver for testing %p
+type P int
+
+var pValue P
+
+func (p *P) String() string {
+ return "String(p)"
+}
+
var b byte
var fmttests = []fmtTest{
fmtTest{"%x", I(23), `3c32333e`},
fmtTest{"%d", I(23), `%d(string=<23>)`},
- // %p on non-pointers
- fmtTest{"%p", make(chan int), "PTR"},
- fmtTest{"%p", make(map[int]int), "PTR"},
- fmtTest{"%p", make([]int, 1), "PTR"},
-
// go syntax
fmtTest{"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`},
fmtTest{"%#v", &b, "(*uint8)(PTR)"},
fmtTest{"%T", intVal, "int"},
fmtTest{"%6T", &intVal, " *int"},
+ // %p
+ fmtTest{"p0=%p", new(int), "p0=PTR"},
+ fmtTest{"p1=%s", &pValue, "p1=String(p)"}, // String method...
+ fmtTest{"p2=%p", &pValue, "p2=PTR"}, // ... not called with %p
+
+ // %p on non-pointers
+ fmtTest{"%p", make(chan int), "PTR"},
+ fmtTest{"%p", make(map[int]int), "PTR"},
+ fmtTest{"%p", make([]int, 1), "PTR"},
+ fmtTest{"%p", 27, "%p(int=27)"}, // not a pointer at all
+
// erroneous things
fmtTest{"%d", "hello", "%d(string=hello)"},
fmtTest{"no args", "hello", "no args?(extra string=hello)"},
}
}
-func (p *pp) fmtUintptrGetter(field interface{}, value reflect.Value, verb int, sharp bool) bool {
+func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSyntax bool) {
v, ok := value.(uintptrGetter)
- if !ok {
- return false
+ if !ok { // reflect.PtrValue is a uintptrGetter, so failure means it's not a pointer at all.
+ p.badVerb(verb, field)
+ return
}
u := v.Get()
- if sharp {
+ if goSyntax {
p.add('(')
p.buf.WriteString(reflect.Typeof(field).String())
p.add(')')
} else {
p.fmt0x64(uint64(u))
}
- return true
}
var (
}
// Special processing considerations.
- // %T (the value's type) is special; we always do it first.
- if verb == 'T' {
+ // %T (the value's type) and %p (its address) are special; we always do them first.
+ switch verb {
+ case 'T':
p.printField(reflect.Typeof(field).String(), 's', false, false, 0)
return false
+ case 'p':
+ p.fmtPointer(field, reflect.NewValue(field), verb, goSyntax)
+ return false
}
// Is it a Formatter?
if formatter, ok := field.(Formatter); ok {
return verb == 's'
}
- value := reflect.NewValue(field)
// Need to use reflection
- // Special case for reflection values that know how to print with %p.
- if verb == 'p' && p.fmtUintptrGetter(field, value, verb, goSyntax) { // TODO: is this goSyntax right?
- return false
- }
+ value := reflect.NewValue(field)
BigSwitch:
switch f := value.(type) {
}
p.fmt0x64(uint64(v))
case uintptrGetter:
- if p.fmtUintptrGetter(field, value, verb, goSyntax) {
- break
- }
- p.unknownType(f)
+ p.fmtPointer(field, value, verb, goSyntax)
default:
p.unknownType(f)
}