1 // Copyright 2017 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
9 "fmt" // TODO: consider copying interfaces from package fmt to avoid dependency.
14 "golang.org/x/text/internal/number"
15 "golang.org/x/text/language"
16 "golang.org/x/text/message/catalog"
19 // Strings for use with buffer.WriteString.
20 // This is less overhead than using buffer.Write with byte arrays.
22 commaSpaceString = ", "
23 nilAngleString = "<nil>"
24 nilParenString = "(nil)"
27 percentBangString = "%!"
28 missingString = "(MISSING)"
29 badIndexString = "(BADINDEX)"
30 panicString = "(PANIC="
31 extraString = "%!(EXTRA "
32 badWidthString = "%!(BADWIDTH)"
33 badPrecString = "%!(BADPREC)"
34 noVerbString = "%!(NOVERB)"
36 invReflectString = "<invalid reflect.Value>"
39 // printer is used to store a printer's state.
40 // It implements "golang.org/x/text/internal/format".State.
42 // the context for looking up message translations
43 catContext *catalog.Context
47 // buffer for accumulating output.
50 // retain arguments across calls.
52 // retain current argument number across calls
54 // arg holds the current item, as an interface{}.
56 // value is used instead of arg for reflect values.
59 // fmt is used to format basic items such as integers or strings.
62 // reordered records whether the format string used argument reordering.
64 // goodArgNum records whether the most recent reordering directive was valid.
66 // panicking is set by catchPanic to avoid infinite panic, recover, panic, ... recursion.
68 // erroring is set when printing an error string to guard against calling handleMethods.
71 toDecimal number.Formatter
72 toScientific number.Formatter
75 func (p *printer) reset() {
84 // Language implements "golang.org/x/text/internal/format".State.
85 func (p *printer) Language() language.Tag { return p.tag }
87 func (p *printer) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent }
89 func (p *printer) Precision() (prec int, ok bool) { return p.fmt.prec, p.fmt.precPresent }
91 func (p *printer) Flag(b int) bool {
96 return p.fmt.plus || p.fmt.plusV
98 return p.fmt.sharp || p.fmt.sharpV
107 // getField gets the i'th field of the struct value.
108 // If the field is itself is an interface, return a value for
109 // the thing inside the interface, not the interface itself.
110 func getField(v reflect.Value, i int) reflect.Value {
112 if val.Kind() == reflect.Interface && !val.IsNil() {
118 // tooLarge reports whether the magnitude of the integer is
119 // too large to be used as a formatting width or precision.
120 func tooLarge(x int) bool {
122 return x > max || x < -max
125 // parsenum converts ASCII to integer. num is 0 (and isnum is false) if no number present.
126 func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
130 for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ {
132 return 0, false, end // Overflow; crazy long number most likely.
134 num = num*10 + int(s[newi]-'0')
140 func (p *printer) unknownType(v reflect.Value) {
142 p.WriteString(nilAngleString)
146 p.WriteString(v.Type().String())
150 func (p *printer) badVerb(verb rune) {
152 p.WriteString(percentBangString)
157 p.WriteString(reflect.TypeOf(p.arg).String())
159 p.printArg(p.arg, 'v')
160 case p.value.IsValid():
161 p.WriteString(p.value.Type().String())
163 p.printValue(p.value, 'v', 0)
165 p.WriteString(nilAngleString)
171 func (p *printer) fmtBool(v bool, verb rune) {
180 // fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or
181 // not, as requested, by temporarily setting the sharp flag.
182 func (p *printer) fmt0x64(v uint64, leading0x bool) {
184 p.fmt.sharp = leading0x
185 p.fmt.fmt_integer(v, 16, unsigned, ldigits)
189 // fmtInteger formats a signed or unsigned integer.
190 func (p *printer) fmtInteger(v uint64, isSigned bool, verb rune) {
193 if p.fmt.sharpV && !isSigned {
199 if p.fmt.sharp || p.fmt.sharpV {
200 p.fmt.fmt_integer(v, 10, isSigned, ldigits)
202 p.fmtDecimalInt(v, isSigned)
205 p.fmt.fmt_integer(v, 2, isSigned, ldigits)
207 p.fmt.fmt_integer(v, 8, isSigned, ldigits)
209 p.fmt.fmt_integer(v, 16, isSigned, ldigits)
211 p.fmt.fmt_integer(v, 16, isSigned, udigits)
215 if v <= utf8.MaxRune {
227 // fmtFloat formats a float. The default precision for each verb
228 // is specified as last argument in the call to fmt_float.
229 func (p *printer) fmtFloat(v float64, size int, verb rune) {
232 p.fmt.fmt_float(v, size, verb, -1)
237 if p.fmt.sharp || p.fmt.sharpV {
238 p.fmt.fmt_float(v, size, verb, -1)
240 p.fmtVariableFloat(v, size)
243 if p.fmt.sharp || p.fmt.sharpV {
244 p.fmt.fmt_float(v, size, verb, 6)
246 p.fmtScientific(v, size, 6)
249 if p.fmt.sharp || p.fmt.sharpV {
250 p.fmt.fmt_float(v, size, verb, 6)
252 p.fmtDecimalFloat(v, size, 6)
259 func (p *printer) setFlags(f *number.Formatter) {
260 f.Flags &^= number.ElideSign
261 if p.fmt.plus || p.fmt.space {
262 f.Flags |= number.AlwaysSign
264 f.Flags |= number.ElideSign
267 f.Flags &^= number.AlwaysSign
271 func (p *printer) updatePadding(f *number.Formatter) {
272 f.Flags &^= number.PadMask
274 f.Flags |= number.PadAfterSuffix
276 f.Flags |= number.PadBeforePrefix
279 f.FormatWidth = uint16(p.fmt.wid)
282 func (p *printer) initDecimal(minFrac, maxFrac int) {
284 f.MinIntegerDigits = 1
285 f.MaxIntegerDigits = 0
286 f.MinFractionDigits = uint8(minFrac)
287 f.MaxFractionDigits = int16(maxFrac)
290 if p.fmt.widPresent {
293 // Use significant integers for this.
294 // TODO: this is not the same as width, but so be it.
295 if f.MinFractionDigits > 0 {
296 wid -= 1 + int(f.MinFractionDigits)
298 if p.fmt.plus || p.fmt.space {
301 if wid > 0 && wid > int(f.MinIntegerDigits) {
302 f.MinIntegerDigits = uint8(wid)
309 func (p *printer) initScientific(minFrac, maxFrac int) {
312 f.SetPrecision(maxFrac)
314 f.SetPrecision(maxFrac + 1)
315 f.MinFractionDigits = uint8(minFrac)
316 f.MaxFractionDigits = int16(maxFrac)
318 f.MinExponentDigits = 2
321 if p.fmt.widPresent {
322 f.Flags &^= number.PadMask
324 f.PadRune = f.Digit(0)
325 f.Flags |= number.PadAfterPrefix
328 f.Flags |= number.PadBeforePrefix
334 func (p *printer) fmtDecimalInt(v uint64, isSigned bool) {
338 if p.fmt.precPresent {
340 f.MinIntegerDigits = uint8(p.fmt.prec)
341 f.MaxIntegerDigits = 0
342 f.MinFractionDigits = 0
343 f.MaxFractionDigits = 0
344 if p.fmt.widPresent {
350 d.ConvertInt(p.toDecimal.RoundingContext, isSigned, v)
352 out := p.toDecimal.Format([]byte(nil), &d)
356 func (p *printer) fmtDecimalFloat(v float64, size, prec int) {
358 if p.fmt.precPresent {
361 p.initDecimal(prec, prec)
362 d.ConvertFloat(p.toDecimal.RoundingContext, v, size)
364 out := p.toDecimal.Format([]byte(nil), &d)
368 func (p *printer) fmtVariableFloat(v float64, size int) {
370 if p.fmt.precPresent {
374 p.initScientific(0, prec)
375 d.ConvertFloat(p.toScientific.RoundingContext, v, size)
377 // Copy logic of 'g' formatting from strconv. It is simplified a bit as
378 // we don't have to mind having prec > len(d.Digits).
384 } else if prec == 0 {
388 exp := int(d.Exp) - 1
389 if exp < -4 || exp >= ePrec {
390 p.initScientific(0, prec)
392 out := p.toScientific.Format([]byte(nil), &d)
395 if prec > int(d.Exp) {
398 if prec -= int(d.Exp); prec < 0 {
401 p.initDecimal(0, prec)
403 out := p.toDecimal.Format([]byte(nil), &d)
408 func (p *printer) fmtScientific(v float64, size, prec int) {
410 if p.fmt.precPresent {
413 p.initScientific(prec, prec)
414 rc := p.toScientific.RoundingContext
415 d.ConvertFloat(rc, v, size)
417 out := p.toScientific.Format([]byte(nil), &d)
422 // fmtComplex formats a complex number v with
423 // r = real(v) and j = imag(v) as (r+ji) using
424 // fmtFloat for r and j formatting.
425 func (p *printer) fmtComplex(v complex128, size int, verb rune) {
426 // Make sure any unsupported verbs are found before the
427 // calls to fmtFloat to not generate an incorrect error string.
429 case 'v', 'b', 'g', 'G', 'f', 'F', 'e', 'E':
431 p.fmtFloat(real(v), size/2, verb)
432 // Imaginary part always has a sign.
433 if math.IsNaN(imag(v)) {
434 // By CLDR's rules, NaNs do not use patterns or signs. As this code
435 // relies on AlwaysSign working for imaginary parts, we need to
436 // manually handle NaNs.
441 nan := f.Symbol(number.SymNan)
443 if w, ok := p.Width(); ok {
444 extra = w - utf8.RuneCountInString(nan) - 1
446 if f.Flags&number.PadAfterNumber == 0 {
447 for ; extra > 0; extra-- {
448 p.WriteRune(f.PadRune)
451 p.WriteString(f.Symbol(number.SymPlusSign))
453 for ; extra > 0; extra-- {
454 p.WriteRune(f.PadRune)
459 oldPlus := p.fmt.plus
461 p.fmtFloat(imag(v), size/2, verb)
462 p.WriteString("i)") // TODO: use symbol?
469 func (p *printer) fmtString(v string, verb rune) {
480 p.fmt.fmt_sx(v, ldigits)
482 p.fmt.fmt_sx(v, udigits)
490 func (p *printer) fmtBytes(v []byte, verb rune, typeString string) {
494 p.WriteString(typeString)
496 p.WriteString(nilParenString)
500 for i, c := range v {
502 p.WriteString(commaSpaceString)
504 p.fmt0x64(uint64(c), true)
509 for i, c := range v {
513 p.fmt.fmt_integer(uint64(c), 10, unsigned, ldigits)
518 p.fmt.fmt_s(string(v))
520 p.fmt.fmt_bx(v, ldigits)
522 p.fmt.fmt_bx(v, udigits)
524 p.fmt.fmt_q(string(v))
526 p.printValue(reflect.ValueOf(v), verb, 0)
530 func (p *printer) fmtPointer(value reflect.Value, verb rune) {
532 switch value.Kind() {
533 case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
544 p.WriteString(value.Type().String())
547 p.WriteString(nilString)
549 p.fmt0x64(uint64(u), true)
554 p.fmt.padString(nilAngleString)
556 p.fmt0x64(uint64(u), !p.fmt.sharp)
560 p.fmt0x64(uint64(u), !p.fmt.sharp)
561 case 'b', 'o', 'd', 'x', 'X':
563 p.fmt.sharp = true // Print as standard go. TODO: does this make sense?
565 p.fmtInteger(uint64(u), unsigned, verb)
571 func (p *printer) catchPanic(arg interface{}, verb rune) {
572 if err := recover(); err != nil {
573 // If it's a nil pointer, just say "<nil>". The likeliest causes are a
574 // Stringer that fails to guard against nil or a nil pointer for a
575 // value receiver, and in either case, "<nil>" is a nice result.
576 if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() {
577 p.WriteString(nilAngleString)
580 // Otherwise print a concise panic message. Most of the time the panic
581 // value will print itself nicely.
583 // Nested panics; the recursion in printArg cannot succeed.
587 oldFlags := p.fmt.fmtFlags
588 // For this output we want default behavior.
591 p.WriteString(percentBangString)
593 p.WriteString(panicString)
599 p.fmt.fmtFlags = oldFlags
603 func (p *printer) handleMethods(verb rune) (handled bool) {
607 // Is it a Formatter?
608 if formatter, ok := p.arg.(fmt.Formatter); ok {
610 defer p.catchPanic(p.arg, verb)
611 formatter.Format(p, verb)
615 // If we're doing Go syntax and the argument knows how to supply it, take care of it now.
617 if stringer, ok := p.arg.(fmt.GoStringer); ok {
619 defer p.catchPanic(p.arg, verb)
620 // Print the result of GoString unadorned.
621 p.fmt.fmt_s(stringer.GoString())
625 // If a string is acceptable according to the format, see if
626 // the value satisfies one of the string-valued interfaces.
627 // Println etc. set verb to %v, which is "stringable".
629 case 'v', 's', 'x', 'X', 'q':
630 // Is it an error or Stringer?
631 // The duplication in the bodies is necessary:
632 // setting handled and deferring catchPanic
633 // must happen before calling the method.
634 switch v := p.arg.(type) {
637 defer p.catchPanic(p.arg, verb)
638 p.fmtString(v.Error(), verb)
643 defer p.catchPanic(p.arg, verb)
644 p.fmtString(v.String(), verb)
652 func (p *printer) printArg(arg interface{}, verb rune) {
654 p.value = reflect.Value{}
659 p.fmt.padString(nilAngleString)
666 // Special processing considerations.
667 // %T (the value's type) and %p (its address) are special; we always do them first.
670 p.fmt.fmt_s(reflect.TypeOf(arg).String())
673 p.fmtPointer(reflect.ValueOf(arg), 'p')
677 // Some types can be done without reflection.
678 switch f := arg.(type) {
682 p.fmtFloat(float64(f), 32, verb)
684 p.fmtFloat(f, 64, verb)
686 p.fmtComplex(complex128(f), 64, verb)
688 p.fmtComplex(f, 128, verb)
690 p.fmtInteger(uint64(f), signed, verb)
692 p.fmtInteger(uint64(f), signed, verb)
694 p.fmtInteger(uint64(f), signed, verb)
696 p.fmtInteger(uint64(f), signed, verb)
698 p.fmtInteger(uint64(f), signed, verb)
700 p.fmtInteger(uint64(f), unsigned, verb)
702 p.fmtInteger(uint64(f), unsigned, verb)
704 p.fmtInteger(uint64(f), unsigned, verb)
706 p.fmtInteger(uint64(f), unsigned, verb)
708 p.fmtInteger(f, unsigned, verb)
710 p.fmtInteger(uint64(f), unsigned, verb)
714 p.fmtBytes(f, verb, "[]byte")
716 // Handle extractable values with special methods
717 // since printValue does not handle them at depth 0.
718 if f.IsValid() && f.CanInterface() {
719 p.arg = f.Interface()
720 if p.handleMethods(verb) {
724 p.printValue(f, verb, 0)
726 // If the type is not simple, it might have methods.
727 if !p.handleMethods(verb) {
728 // Need to use reflection, since the type had no
729 // interface methods that could be used for formatting.
730 p.printValue(reflect.ValueOf(f), verb, 0)
735 // printValue is similar to printArg but starts with a reflect value, not an interface{} value.
736 // It does not handle 'p' and 'T' verbs because these should have been already handled by printArg.
737 func (p *printer) printValue(value reflect.Value, verb rune, depth int) {
738 // Handle values with special methods if not already handled by printArg (depth == 0).
739 if depth > 0 && value.IsValid() && value.CanInterface() {
740 p.arg = value.Interface()
741 if p.handleMethods(verb) {
748 switch f := value; value.Kind() {
749 case reflect.Invalid:
751 p.WriteString(invReflectString)
755 p.WriteString(nilAngleString)
761 p.fmtBool(f.Bool(), verb)
762 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
763 p.fmtInteger(uint64(f.Int()), signed, verb)
764 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
765 p.fmtInteger(f.Uint(), unsigned, verb)
766 case reflect.Float32:
767 p.fmtFloat(f.Float(), 32, verb)
768 case reflect.Float64:
769 p.fmtFloat(f.Float(), 64, verb)
770 case reflect.Complex64:
771 p.fmtComplex(f.Complex(), 64, verb)
772 case reflect.Complex128:
773 p.fmtComplex(f.Complex(), 128, verb)
775 p.fmtString(f.String(), verb)
778 p.WriteString(f.Type().String())
780 p.WriteString(nilParenString)
785 p.WriteString(mapString)
788 for i, key := range keys {
791 p.WriteString(commaSpaceString)
796 p.printValue(key, verb, depth+1)
798 p.printValue(f.MapIndex(key), verb, depth+1)
807 p.WriteString(f.Type().String())
810 for i := 0; i < f.NumField(); i++ {
813 p.WriteString(commaSpaceString)
818 if p.fmt.plusV || p.fmt.sharpV {
819 if name := f.Type().Field(i).Name; name != "" {
824 p.printValue(getField(f, i), verb, depth+1)
827 case reflect.Interface:
829 if !value.IsValid() {
831 p.WriteString(f.Type().String())
832 p.WriteString(nilParenString)
834 p.WriteString(nilAngleString)
837 p.printValue(value, verb, depth+1)
839 case reflect.Array, reflect.Slice:
841 case 's', 'q', 'x', 'X':
842 // Handle byte and uint8 slices and arrays special for the above verbs.
844 if t.Elem().Kind() == reflect.Uint8 {
846 if f.Kind() == reflect.Slice {
848 } else if f.CanAddr() {
849 bytes = f.Slice(0, f.Len()).Bytes()
851 // We have an array, but we cannot Slice() a non-addressable array,
852 // so we build a slice by hand. This is a rare case but it would be nice
853 // if reflection could help a little more.
854 bytes = make([]byte, f.Len())
855 for i := range bytes {
856 bytes[i] = byte(f.Index(i).Uint())
859 p.fmtBytes(bytes, verb, t.String())
864 p.WriteString(f.Type().String())
865 if f.Kind() == reflect.Slice && f.IsNil() {
866 p.WriteString(nilParenString)
870 for i := 0; i < f.Len(); i++ {
872 p.WriteString(commaSpaceString)
874 p.printValue(f.Index(i), verb, depth+1)
879 for i := 0; i < f.Len(); i++ {
883 p.printValue(f.Index(i), verb, depth+1)
888 // pointer to array or slice or struct? ok at top level
889 // but not embedded (avoid loops)
890 if depth == 0 && f.Pointer() != 0 {
891 switch a := f.Elem(); a.Kind() {
892 case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map:
894 p.printValue(a, verb, depth+1)
899 case reflect.Chan, reflect.Func, reflect.UnsafePointer:
900 p.fmtPointer(f, verb)
906 // intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has integer type.
907 func (p *printer) intFromArg() (num int, isInt bool) {
908 if p.argNum < len(p.args) {
909 arg := p.args[p.argNum]
910 num, isInt = arg.(int) // Almost always OK.
913 switch v := reflect.ValueOf(arg); v.Kind() {
914 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
916 if int64(int(n)) == n {
920 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
922 if int64(n) >= 0 && uint64(int(n)) == n {
939 // parseArgNumber returns the value of the bracketed number, minus 1
940 // (explicit argument numbers are one-indexed but we want zero-indexed).
941 // The opening bracket is known to be present at format[0].
942 // The returned values are the index, the number of bytes to consume
943 // up to the closing paren, if present, and whether the number parsed
944 // ok. The bytes to consume will be 1 if no closing paren is present.
945 func parseArgNumber(format string) (index int, wid int, ok bool) {
946 // There must be at least 3 bytes: [n].
951 // Find closing bracket.
952 for i := 1; i < len(format); i++ {
953 if format[i] == ']' {
954 width, ok, newi := parsenum(format, 1, i)
955 if !ok || newi != i {
956 return 0, i + 1, false
958 return width - 1, i + 1, true // arg numbers are one-indexed and skip paren.
964 // updateArgNumber returns the next argument to evaluate, which is either the value of the passed-in
965 // argNum or the value of the bracketed integer that begins format[i:]. It also returns
966 // the new value of i, that is, the index of the next byte of the format to process.
967 func (p *printer) updateArgNumber(format string, i int) (newi int, found bool) {
968 if len(format) <= i || format[i] != '[' {
972 index, wid, ok := parseArgNumber(format[i:])
973 if ok && 0 <= index && index < len(p.args) {
981 func (p *printer) badArgNum(verb rune) {
982 p.WriteString(percentBangString)
984 p.WriteString(badIndexString)
987 func (p *printer) missingArg(verb rune) {
988 p.WriteString(percentBangString)
990 p.WriteString(missingString)
993 func (p *printer) doPrintf(format string) {
995 afterIndex := false // previous item in format was an index like [3].
997 for i := 0; i < end; {
1000 for i < end && format[i] != '%' {
1004 p.WriteString(format[lasti:i])
1007 // done processing format string
1014 // Do we have flags?
1017 for ; i < end; i++ {
1023 p.fmt.zero = !p.fmt.minus // Only allow zero padding to the left.
1028 p.fmt.zero = false // Do not pad with zeros to the right.
1032 // Fast path for common case of ascii lower case simple verbs
1033 // without precision or width or argument indices.
1034 if 'a' <= c && c <= 'z' && p.argNum < len(p.args) {
1037 p.fmt.sharpV = p.fmt.sharp
1039 // Struct-field syntax
1040 p.fmt.plusV = p.fmt.plus
1043 p.printArg(p.Arg(p.argNum+1), rune(c))
1048 // Format is more complex than simple flags and a verb or is malformed.
1053 // Do we have an explicit argument index?
1054 i, afterIndex = p.updateArgNumber(format, i)
1056 // Do we have width?
1057 if i < end && format[i] == '*' {
1059 p.fmt.wid, p.fmt.widPresent = p.intFromArg()
1061 if !p.fmt.widPresent {
1062 p.WriteString(badWidthString)
1065 // We have a negative width, so take its value and ensure
1066 // that the minus flag is set
1068 p.fmt.wid = -p.fmt.wid
1070 p.fmt.zero = false // Do not pad with zeros to the right.
1074 p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end)
1075 if afterIndex && p.fmt.widPresent { // "%[3]2d"
1076 p.goodArgNum = false
1080 // Do we have precision?
1081 if i+1 < end && format[i] == '.' {
1083 if afterIndex { // "%[3].2d"
1084 p.goodArgNum = false
1086 i, afterIndex = p.updateArgNumber(format, i)
1087 if i < end && format[i] == '*' {
1089 p.fmt.prec, p.fmt.precPresent = p.intFromArg()
1090 // Negative precision arguments don't make sense
1093 p.fmt.precPresent = false
1095 if !p.fmt.precPresent {
1096 p.WriteString(badPrecString)
1100 p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i, end)
1101 if !p.fmt.precPresent {
1103 p.fmt.precPresent = true
1109 i, afterIndex = p.updateArgNumber(format, i)
1113 p.WriteString(noVerbString)
1117 verb, w := utf8.DecodeRuneInString(format[i:])
1121 case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec.
1125 case p.argNum >= len(p.args): // No argument left over to print for the current verb.
1129 p.fmt.sharpV = p.fmt.sharp
1131 // Struct-field syntax
1132 p.fmt.plusV = p.fmt.plus
1136 p.printArg(p.args[p.argNum], verb)
1141 // Check for extra arguments, but only if there was at least one ordered
1142 // argument. Note that this behavior is necessarily different from fmt:
1143 // different variants of messages may opt to drop some or all of the
1145 if !p.reordered && p.argNum < len(p.args) && p.argNum != 0 {
1147 p.WriteString(extraString)
1148 for i, arg := range p.args[p.argNum:] {
1150 p.WriteString(commaSpaceString)
1153 p.WriteString(nilAngleString)
1155 p.WriteString(reflect.TypeOf(arg).String())
1157 p.printArg(arg, 'v')
1164 func (p *printer) doPrint(a []interface{}) {
1166 for argNum, arg := range a {
1167 isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
1168 // Add a space between two non-string arguments.
1169 if argNum > 0 && !isString && !prevString {
1172 p.printArg(arg, 'v')
1173 prevString = isString
1177 // doPrintln is like doPrint but always adds a space between arguments
1178 // and a newline after the last argument.
1179 func (p *printer) doPrintln(a []interface{}) {
1180 for argNum, arg := range a {
1184 p.printArg(arg, 'v')