in message/print.go [733:900]
func (p *printer) printValue(value reflect.Value, verb rune, depth int) {
// Handle values with special methods if not already handled by printArg (depth == 0).
if depth > 0 && value.IsValid() && value.CanInterface() {
p.arg = value.Interface()
if p.handleMethods(verb) {
return
}
}
p.arg = nil
p.value = value
switch f := value; value.Kind() {
case reflect.Invalid:
if depth == 0 {
p.WriteString(invReflectString)
} else {
switch verb {
case 'v':
p.WriteString(nilAngleString)
default:
p.badVerb(verb)
}
}
case reflect.Bool:
p.fmtBool(f.Bool(), verb)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p.fmtInteger(uint64(f.Int()), signed, verb)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p.fmtInteger(f.Uint(), unsigned, verb)
case reflect.Float32:
p.fmtFloat(f.Float(), 32, verb)
case reflect.Float64:
p.fmtFloat(f.Float(), 64, verb)
case reflect.Complex64:
p.fmtComplex(f.Complex(), 64, verb)
case reflect.Complex128:
p.fmtComplex(f.Complex(), 128, verb)
case reflect.String:
p.fmtString(f.String(), verb)
case reflect.Map:
if p.fmt.SharpV {
p.WriteString(f.Type().String())
if f.IsNil() {
p.WriteString(nilParenString)
return
}
p.WriteByte('{')
} else {
p.WriteString(mapString)
}
keys := f.MapKeys()
for i, key := range keys {
if i > 0 {
if p.fmt.SharpV {
p.WriteString(commaSpaceString)
} else {
p.WriteByte(' ')
}
}
p.printValue(key, verb, depth+1)
p.WriteByte(':')
p.printValue(f.MapIndex(key), verb, depth+1)
}
if p.fmt.SharpV {
p.WriteByte('}')
} else {
p.WriteByte(']')
}
case reflect.Struct:
if p.fmt.SharpV {
p.WriteString(f.Type().String())
}
p.WriteByte('{')
for i := 0; i < f.NumField(); i++ {
if i > 0 {
if p.fmt.SharpV {
p.WriteString(commaSpaceString)
} else {
p.WriteByte(' ')
}
}
if p.fmt.PlusV || p.fmt.SharpV {
if name := f.Type().Field(i).Name; name != "" {
p.WriteString(name)
p.WriteByte(':')
}
}
p.printValue(getField(f, i), verb, depth+1)
}
p.WriteByte('}')
case reflect.Interface:
value := f.Elem()
if !value.IsValid() {
if p.fmt.SharpV {
p.WriteString(f.Type().String())
p.WriteString(nilParenString)
} else {
p.WriteString(nilAngleString)
}
} else {
p.printValue(value, verb, depth+1)
}
case reflect.Array, reflect.Slice:
switch verb {
case 's', 'q', 'x', 'X':
// Handle byte and uint8 slices and arrays special for the above verbs.
t := f.Type()
if t.Elem().Kind() == reflect.Uint8 {
var bytes []byte
if f.Kind() == reflect.Slice {
bytes = f.Bytes()
} else if f.CanAddr() {
bytes = f.Slice(0, f.Len()).Bytes()
} else {
// We have an array, but we cannot Slice() a non-addressable array,
// so we build a slice by hand. This is a rare case but it would be nice
// if reflection could help a little more.
bytes = make([]byte, f.Len())
for i := range bytes {
bytes[i] = byte(f.Index(i).Uint())
}
}
p.fmtBytes(bytes, verb, t.String())
return
}
}
if p.fmt.SharpV {
p.WriteString(f.Type().String())
if f.Kind() == reflect.Slice && f.IsNil() {
p.WriteString(nilParenString)
return
}
p.WriteByte('{')
for i := 0; i < f.Len(); i++ {
if i > 0 {
p.WriteString(commaSpaceString)
}
p.printValue(f.Index(i), verb, depth+1)
}
p.WriteByte('}')
} else {
p.WriteByte('[')
for i := 0; i < f.Len(); i++ {
if i > 0 {
p.WriteByte(' ')
}
p.printValue(f.Index(i), verb, depth+1)
}
p.WriteByte(']')
}
case reflect.Ptr:
// pointer to array or slice or struct? ok at top level
// but not embedded (avoid loops)
if depth == 0 && f.Pointer() != 0 {
switch a := f.Elem(); a.Kind() {
case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map:
p.WriteByte('&')
p.printValue(a, verb, depth+1)
return
}
}
fallthrough
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
p.fmtPointer(f, verb)
default:
p.unknownType(f)
}
}