package fmt
import (
"internal/fmtsort"
"io"
"os"
"reflect"
"strconv"
"sync"
"unicode/utf8"
)
const (
commaSpaceString = ", "
nilAngleString = "<nil>"
nilParenString = "(nil)"
nilString = "nil"
mapString = "map["
percentBangString = "%!"
missingString = "(MISSING)"
badIndexString = "(BADINDEX)"
panicString = "(PANIC="
extraString = "%!(EXTRA "
badWidthString = "%!(BADWIDTH)"
badPrecString = "%!(BADPREC)"
noVerbString = "%!(NOVERB)"
invReflectString = "<invalid reflect.Value>"
)
type State interface {
Write (b []byte ) (n int , err error )
Width () (wid int , ok bool )
Precision () (prec int , ok bool )
Flag (c int ) bool
}
type Formatter interface {
Format (f State , verb rune )
}
type Stringer interface {
String () string
}
type GoStringer interface {
GoString () string
}
func FormatString (state State , verb rune ) string {
var tmp [16 ]byte
b := append (tmp [:0 ], '%' )
for _ , c := range " +-#0" {
if state .Flag (int (c )) {
b = append (b , byte (c ))
}
}
if w , ok := state .Width (); ok {
b = strconv .AppendInt (b , int64 (w ), 10 )
}
if p , ok := state .Precision (); ok {
b = append (b , '.' )
b = strconv .AppendInt (b , int64 (p ), 10 )
}
b = utf8 .AppendRune (b , verb )
return string (b )
}
type buffer []byte
func (b *buffer ) write (p []byte ) {
*b = append (*b , p ...)
}
func (b *buffer ) writeString (s string ) {
*b = append (*b , s ...)
}
func (b *buffer ) writeByte (c byte ) {
*b = append (*b , c )
}
func (bp *buffer ) writeRune (r rune ) {
*bp = utf8 .AppendRune (*bp , r )
}
type pp struct {
buf buffer
arg any
value reflect .Value
fmt fmt
reordered bool
goodArgNum bool
panicking bool
erroring bool
wrapErrs bool
wrappedErrs []int
}
var ppFree = sync .Pool {
New : func () any { return new (pp ) },
}
func newPrinter () *pp {
p := ppFree .Get ().(*pp )
p .panicking = false
p .erroring = false
p .wrapErrs = false
p .fmt .init (&p .buf )
return p
}
func (p *pp ) free () {
if cap (p .buf ) > 64 *1024 {
p .buf = nil
} else {
p .buf = p .buf [:0 ]
}
if cap (p .wrappedErrs ) > 8 {
p .wrappedErrs = nil
}
p .arg = nil
p .value = reflect .Value {}
p .wrappedErrs = p .wrappedErrs [:0 ]
ppFree .Put (p )
}
func (p *pp ) Width () (wid int , ok bool ) { return p .fmt .wid , p .fmt .widPresent }
func (p *pp ) Precision () (prec int , ok bool ) { return p .fmt .prec , p .fmt .precPresent }
func (p *pp ) Flag (b int ) bool {
switch b {
case '-' :
return p .fmt .minus
case '+' :
return p .fmt .plus || p .fmt .plusV
case '#' :
return p .fmt .sharp || p .fmt .sharpV
case ' ' :
return p .fmt .space
case '0' :
return p .fmt .zero
}
return false
}
func (p *pp ) Write (b []byte ) (ret int , err error ) {
p .buf .write (b )
return len (b ), nil
}
func (p *pp ) WriteString (s string ) (ret int , err error ) {
p .buf .writeString (s )
return len (s ), nil
}
func Fprintf (w io .Writer , format string , a ...any ) (n int , err error ) {
p := newPrinter ()
p .doPrintf (format , a )
n , err = w .Write (p .buf )
p .free ()
return
}
func Printf (format string , a ...any ) (n int , err error ) {
return Fprintf (os .Stdout , format , a ...)
}
func Sprintf (format string , a ...any ) string {
p := newPrinter ()
p .doPrintf (format , a )
s := string (p .buf )
p .free ()
return s
}
func Appendf (b []byte , format string , a ...any ) []byte {
p := newPrinter ()
p .doPrintf (format , a )
b = append (b , p .buf ...)
p .free ()
return b
}
func Fprint (w io .Writer , a ...any ) (n int , err error ) {
p := newPrinter ()
p .doPrint (a )
n , err = w .Write (p .buf )
p .free ()
return
}
func Print (a ...any ) (n int , err error ) {
return Fprint (os .Stdout , a ...)
}
func Sprint (a ...any ) string {
p := newPrinter ()
p .doPrint (a )
s := string (p .buf )
p .free ()
return s
}
func Append (b []byte , a ...any ) []byte {
p := newPrinter ()
p .doPrint (a )
b = append (b , p .buf ...)
p .free ()
return b
}
func Fprintln (w io .Writer , a ...any ) (n int , err error ) {
p := newPrinter ()
p .doPrintln (a )
n , err = w .Write (p .buf )
p .free ()
return
}
func Println (a ...any ) (n int , err error ) {
return Fprintln (os .Stdout , a ...)
}
func Sprintln (a ...any ) string {
p := newPrinter ()
p .doPrintln (a )
s := string (p .buf )
p .free ()
return s
}
func Appendln (b []byte , a ...any ) []byte {
p := newPrinter ()
p .doPrintln (a )
b = append (b , p .buf ...)
p .free ()
return b
}
func getField (v reflect .Value , i int ) reflect .Value {
val := v .Field (i )
if val .Kind () == reflect .Interface && !val .IsNil () {
val = val .Elem ()
}
return val
}
func tooLarge (x int ) bool {
const max int = 1e6
return x > max || x < -max
}
func parsenum (s string , start , end int ) (num int , isnum bool , newi int ) {
if start >= end {
return 0 , false , end
}
for newi = start ; newi < end && '0' <= s [newi ] && s [newi ] <= '9' ; newi ++ {
if tooLarge (num ) {
return 0 , false , end
}
num = num *10 + int (s [newi ]-'0' )
isnum = true
}
return
}
func (p *pp ) unknownType (v reflect .Value ) {
if !v .IsValid () {
p .buf .writeString (nilAngleString )
return
}
p .buf .writeByte ('?' )
p .buf .writeString (v .Type ().String ())
p .buf .writeByte ('?' )
}
func (p *pp ) badVerb (verb rune ) {
p .erroring = true
p .buf .writeString (percentBangString )
p .buf .writeRune (verb )
p .buf .writeByte ('(' )
switch {
case p .arg != nil :
p .buf .writeString (reflect .TypeOf (p .arg ).String ())
p .buf .writeByte ('=' )
p .printArg (p .arg , 'v' )
case p .value .IsValid ():
p .buf .writeString (p .value .Type ().String ())
p .buf .writeByte ('=' )
p .printValue (p .value , 'v' , 0 )
default :
p .buf .writeString (nilAngleString )
}
p .buf .writeByte (')' )
p .erroring = false
}
func (p *pp ) fmtBool (v bool , verb rune ) {
switch verb {
case 't' , 'v' :
p .fmt .fmtBoolean (v )
default :
p .badVerb (verb )
}
}
func (p *pp ) fmt0x64 (v uint64 , leading0x bool ) {
sharp := p .fmt .sharp
p .fmt .sharp = leading0x
p .fmt .fmtInteger (v , 16 , unsigned , 'v' , ldigits )
p .fmt .sharp = sharp
}
func (p *pp ) fmtInteger (v uint64 , isSigned bool , verb rune ) {
switch verb {
case 'v' :
if p .fmt .sharpV && !isSigned {
p .fmt0x64 (v , true )
} else {
p .fmt .fmtInteger (v , 10 , isSigned , verb , ldigits )
}
case 'd' :
p .fmt .fmtInteger (v , 10 , isSigned , verb , ldigits )
case 'b' :
p .fmt .fmtInteger (v , 2 , isSigned , verb , ldigits )
case 'o' , 'O' :
p .fmt .fmtInteger (v , 8 , isSigned , verb , ldigits )
case 'x' :
p .fmt .fmtInteger (v , 16 , isSigned , verb , ldigits )
case 'X' :
p .fmt .fmtInteger (v , 16 , isSigned , verb , udigits )
case 'c' :
p .fmt .fmtC (v )
case 'q' :
p .fmt .fmtQc (v )
case 'U' :
p .fmt .fmtUnicode (v )
default :
p .badVerb (verb )
}
}
func (p *pp ) fmtFloat (v float64 , size int , verb rune ) {
switch verb {
case 'v' :
p .fmt .fmtFloat (v , size , 'g' , -1 )
case 'b' , 'g' , 'G' , 'x' , 'X' :
p .fmt .fmtFloat (v , size , verb , -1 )
case 'f' , 'e' , 'E' :
p .fmt .fmtFloat (v , size , verb , 6 )
case 'F' :
p .fmt .fmtFloat (v , size , 'f' , 6 )
default :
p .badVerb (verb )
}
}
func (p *pp ) fmtComplex (v complex128 , size int , verb rune ) {
switch verb {
case 'v' , 'b' , 'g' , 'G' , 'x' , 'X' , 'f' , 'F' , 'e' , 'E' :
oldPlus := p .fmt .plus
p .buf .writeByte ('(' )
p .fmtFloat (real (v ), size /2 , verb )
p .fmt .plus = true
p .fmtFloat (imag (v ), size /2 , verb )
p .buf .writeString ("i)" )
p .fmt .plus = oldPlus
default :
p .badVerb (verb )
}
}
func (p *pp ) fmtString (v string , verb rune ) {
switch verb {
case 'v' :
if p .fmt .sharpV {
p .fmt .fmtQ (v )
} else {
p .fmt .fmtS (v )
}
case 's' :
p .fmt .fmtS (v )
case 'x' :
p .fmt .fmtSx (v , ldigits )
case 'X' :
p .fmt .fmtSx (v , udigits )
case 'q' :
p .fmt .fmtQ (v )
default :
p .badVerb (verb )
}
}
func (p *pp ) fmtBytes (v []byte , verb rune , typeString string ) {
switch verb {
case 'v' , 'd' :
if p .fmt .sharpV {
p .buf .writeString (typeString )
if v == nil {
p .buf .writeString (nilParenString )
return
}
p .buf .writeByte ('{' )
for i , c := range v {
if i > 0 {
p .buf .writeString (commaSpaceString )
}
p .fmt0x64 (uint64 (c ), true )
}
p .buf .writeByte ('}' )
} else {
p .buf .writeByte ('[' )
for i , c := range v {
if i > 0 {
p .buf .writeByte (' ' )
}
p .fmt .fmtInteger (uint64 (c ), 10 , unsigned , verb , ldigits )
}
p .buf .writeByte (']' )
}
case 's' :
p .fmt .fmtBs (v )
case 'x' :
p .fmt .fmtBx (v , ldigits )
case 'X' :
p .fmt .fmtBx (v , udigits )
case 'q' :
p .fmt .fmtQ (string (v ))
default :
p .printValue (reflect .ValueOf (v ), verb , 0 )
}
}
func (p *pp ) fmtPointer (value reflect .Value , verb rune ) {
var u uintptr
switch value .Kind () {
case reflect .Chan , reflect .Func , reflect .Map , reflect .Pointer , reflect .Slice , reflect .UnsafePointer :
u = value .Pointer ()
default :
p .badVerb (verb )
return
}
switch verb {
case 'v' :
if p .fmt .sharpV {
p .buf .writeByte ('(' )
p .buf .writeString (value .Type ().String ())
p .buf .writeString (")(" )
if u == 0 {
p .buf .writeString (nilString )
} else {
p .fmt0x64 (uint64 (u ), true )
}
p .buf .writeByte (')' )
} else {
if u == 0 {
p .fmt .padString (nilAngleString )
} else {
p .fmt0x64 (uint64 (u ), !p .fmt .sharp )
}
}
case 'p' :
p .fmt0x64 (uint64 (u ), !p .fmt .sharp )
case 'b' , 'o' , 'd' , 'x' , 'X' :
p .fmtInteger (uint64 (u ), unsigned , verb )
default :
p .badVerb (verb )
}
}
func (p *pp ) catchPanic (arg any , verb rune , method string ) {
if err := recover (); err != nil {
if v := reflect .ValueOf (arg ); v .Kind () == reflect .Pointer && v .IsNil () {
p .buf .writeString (nilAngleString )
return
}
if p .panicking {
panic (err )
}
oldFlags := p .fmt .fmtFlags
p .fmt .clearflags ()
p .buf .writeString (percentBangString )
p .buf .writeRune (verb )
p .buf .writeString (panicString )
p .buf .writeString (method )
p .buf .writeString (" method: " )
p .panicking = true
p .printArg (err , 'v' )
p .panicking = false
p .buf .writeByte (')' )
p .fmt .fmtFlags = oldFlags
}
}
func (p *pp ) handleMethods (verb rune ) (handled bool ) {
if p .erroring {
return
}
if verb == 'w' {
_ , ok := p .arg .(error )
if !ok || !p .wrapErrs {
p .badVerb (verb )
return true
}
verb = 'v'
}
if formatter , ok := p .arg .(Formatter ); ok {
handled = true
defer p .catchPanic (p .arg , verb , "Format" )
formatter .Format (p , verb )
return
}
if p .fmt .sharpV {
if stringer , ok := p .arg .(GoStringer ); ok {
handled = true
defer p .catchPanic (p .arg , verb , "GoString" )
p .fmt .fmtS (stringer .GoString ())
return
}
} else {
switch verb {
case 'v' , 's' , 'x' , 'X' , 'q' :
switch v := p .arg .(type ) {
case error :
handled = true
defer p .catchPanic (p .arg , verb , "Error" )
p .fmtString (v .Error(), verb )
return
case Stringer :
handled = true
defer p .catchPanic (p .arg , verb , "String" )
p .fmtString (v .String (), verb )
return
}
}
}
return false
}
func (p *pp ) printArg (arg any , verb rune ) {
p .arg = arg
p .value = reflect .Value {}
if arg == nil {
switch verb {
case 'T' , 'v' :
p .fmt .padString (nilAngleString )
default :
p .badVerb (verb )
}
return
}
switch verb {
case 'T' :
p .fmt .fmtS (reflect .TypeOf (arg ).String ())
return
case 'p' :
p .fmtPointer (reflect .ValueOf (arg ), 'p' )
return
}
switch f := arg .(type ) {
case bool :
p .fmtBool (f , verb )
case float32 :
p .fmtFloat (float64 (f ), 32 , verb )
case float64 :
p .fmtFloat (f , 64 , verb )
case complex64 :
p .fmtComplex (complex128 (f ), 64 , verb )
case complex128 :
p .fmtComplex (f , 128 , verb )
case int :
p .fmtInteger (uint64 (f ), signed , verb )
case int8 :
p .fmtInteger (uint64 (f ), signed , verb )
case int16 :
p .fmtInteger (uint64 (f ), signed , verb )
case int32 :
p .fmtInteger (uint64 (f ), signed , verb )
case int64 :
p .fmtInteger (uint64 (f ), signed , verb )
case uint :
p .fmtInteger (uint64 (f ), unsigned , verb )
case uint8 :
p .fmtInteger (uint64 (f ), unsigned , verb )
case uint16 :
p .fmtInteger (uint64 (f ), unsigned , verb )
case uint32 :
p .fmtInteger (uint64 (f ), unsigned , verb )
case uint64 :
p .fmtInteger (f , unsigned , verb )
case uintptr :
p .fmtInteger (uint64 (f ), unsigned , verb )
case string :
p .fmtString (f , verb )
case []byte :
p .fmtBytes (f , verb , "[]byte" )
case reflect .Value :
if f .IsValid () && f .CanInterface () {
p .arg = f .Interface ()
if p .handleMethods (verb ) {
return
}
}
p .printValue (f , verb , 0 )
default :
if !p .handleMethods (verb ) {
p .printValue (reflect .ValueOf (f ), verb , 0 )
}
}
}
func (p *pp ) printValue (value reflect .Value , verb rune , depth int ) {
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 .buf .writeString (invReflectString )
} else {
switch verb {
case 'v' :
p .buf .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 .buf .writeString (f .Type ().String ())
if f .IsNil () {
p .buf .writeString (nilParenString )
return
}
p .buf .writeByte ('{' )
} else {
p .buf .writeString (mapString )
}
sorted := fmtsort .Sort (f )
for i , key := range sorted .Key {
if i > 0 {
if p .fmt .sharpV {
p .buf .writeString (commaSpaceString )
} else {
p .buf .writeByte (' ' )
}
}
p .printValue (key , verb , depth +1 )
p .buf .writeByte (':' )
p .printValue (sorted .Value [i ], verb , depth +1 )
}
if p .fmt .sharpV {
p .buf .writeByte ('}' )
} else {
p .buf .writeByte (']' )
}
case reflect .Struct :
if p .fmt .sharpV {
p .buf .writeString (f .Type ().String ())
}
p .buf .writeByte ('{' )
for i := 0 ; i < f .NumField (); i ++ {
if i > 0 {
if p .fmt .sharpV {
p .buf .writeString (commaSpaceString )
} else {
p .buf .writeByte (' ' )
}
}
if p .fmt .plusV || p .fmt .sharpV {
if name := f .Type ().Field (i ).Name ; name != "" {
p .buf .writeString (name )
p .buf .writeByte (':' )
}
}
p .printValue (getField (f , i ), verb , depth +1 )
}
p .buf .writeByte ('}' )
case reflect .Interface :
value := f .Elem ()
if !value .IsValid () {
if p .fmt .sharpV {
p .buf .writeString (f .Type ().String ())
p .buf .writeString (nilParenString )
} else {
p .buf .writeString (nilAngleString )
}
} else {
p .printValue (value , verb , depth +1 )
}
case reflect .Array , reflect .Slice :
switch verb {
case 's' , 'q' , 'x' , 'X' :
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 {
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 .buf .writeString (f .Type ().String ())
if f .Kind () == reflect .Slice && f .IsNil () {
p .buf .writeString (nilParenString )
return
}
p .buf .writeByte ('{' )
for i := 0 ; i < f .Len (); i ++ {
if i > 0 {
p .buf .writeString (commaSpaceString )
}
p .printValue (f .Index (i ), verb , depth +1 )
}
p .buf .writeByte ('}' )
} else {
p .buf .writeByte ('[' )
for i := 0 ; i < f .Len (); i ++ {
if i > 0 {
p .buf .writeByte (' ' )
}
p .printValue (f .Index (i ), verb , depth +1 )
}
p .buf .writeByte (']' )
}
case reflect .Pointer :
if depth == 0 && f .Pointer () != 0 {
switch a := f .Elem (); a .Kind () {
case reflect .Array , reflect .Slice , reflect .Struct , reflect .Map :
p .buf .writeByte ('&' )
p .printValue (a , verb , depth +1 )
return
}
}
fallthrough
case reflect .Chan , reflect .Func , reflect .UnsafePointer :
p .fmtPointer (f , verb )
default :
p .unknownType (f )
}
}
func intFromArg (a []any , argNum int ) (num int , isInt bool , newArgNum int ) {
newArgNum = argNum
if argNum < len (a ) {
num , isInt = a [argNum ].(int )
if !isInt {
switch v := reflect .ValueOf (a [argNum ]); v .Kind () {
case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
n := v .Int ()
if int64 (int (n )) == n {
num = int (n )
isInt = true
}
case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr :
n := v .Uint ()
if int64 (n ) >= 0 && uint64 (int (n )) == n {
num = int (n )
isInt = true
}
default :
}
}
newArgNum = argNum + 1
if tooLarge (num ) {
num = 0
isInt = false
}
}
return
}
func parseArgNumber (format string ) (index int , wid int , ok bool ) {
if len (format ) < 3 {
return 0 , 1 , false
}
for i := 1 ; i < len (format ); i ++ {
if format [i ] == ']' {
width , ok , newi := parsenum (format , 1 , i )
if !ok || newi != i {
return 0 , i + 1 , false
}
return width - 1 , i + 1 , true
}
}
return 0 , 1 , false
}
func (p *pp ) argNumber (argNum int , format string , i int , numArgs int ) (newArgNum , newi int , found bool ) {
if len (format ) <= i || format [i ] != '[' {
return argNum , i , false
}
p .reordered = true
index , wid , ok := parseArgNumber (format [i :])
if ok && 0 <= index && index < numArgs {
return index , i + wid , true
}
p .goodArgNum = false
return argNum , i + wid , ok
}
func (p *pp ) badArgNum (verb rune ) {
p .buf .writeString (percentBangString )
p .buf .writeRune (verb )
p .buf .writeString (badIndexString )
}
func (p *pp ) missingArg (verb rune ) {
p .buf .writeString (percentBangString )
p .buf .writeRune (verb )
p .buf .writeString (missingString )
}
func (p *pp ) doPrintf (format string , a []any ) {
end := len (format )
argNum := 0
afterIndex := false
p .reordered = false
formatLoop :
for i := 0 ; i < end ; {
p .goodArgNum = true
lasti := i
for i < end && format [i ] != '%' {
i ++
}
if i > lasti {
p .buf .writeString (format [lasti :i ])
}
if i >= end {
break
}
i ++
p .fmt .clearflags ()
simpleFormat :
for ; i < end ; i ++ {
c := format [i ]
switch c {
case '#' :
p .fmt .sharp = true
case '0' :
p .fmt .zero = !p .fmt .minus
case '+' :
p .fmt .plus = true
case '-' :
p .fmt .minus = true
p .fmt .zero = false
case ' ' :
p .fmt .space = true
default :
if 'a' <= c && c <= 'z' && argNum < len (a ) {
switch c {
case 'w' :
p .wrappedErrs = append (p .wrappedErrs , argNum )
fallthrough
case 'v' :
p .fmt .sharpV = p .fmt .sharp
p .fmt .sharp = false
p .fmt .plusV = p .fmt .plus
p .fmt .plus = false
}
p .printArg (a [argNum ], rune (c ))
argNum ++
i ++
continue formatLoop
}
break simpleFormat
}
}
argNum , i , afterIndex = p .argNumber (argNum , format , i , len (a ))
if i < end && format [i ] == '*' {
i ++
p .fmt .wid , p .fmt .widPresent , argNum = intFromArg (a , argNum )
if !p .fmt .widPresent {
p .buf .writeString (badWidthString )
}
if p .fmt .wid < 0 {
p .fmt .wid = -p .fmt .wid
p .fmt .minus = true
p .fmt .zero = false
}
afterIndex = false
} else {
p .fmt .wid , p .fmt .widPresent , i = parsenum (format , i , end )
if afterIndex && p .fmt .widPresent {
p .goodArgNum = false
}
}
if i +1 < end && format [i ] == '.' {
i ++
if afterIndex {
p .goodArgNum = false
}
argNum , i , afterIndex = p .argNumber (argNum , format , i , len (a ))
if i < end && format [i ] == '*' {
i ++
p .fmt .prec , p .fmt .precPresent , argNum = intFromArg (a , argNum )
if p .fmt .prec < 0 {
p .fmt .prec = 0
p .fmt .precPresent = false
}
if !p .fmt .precPresent {
p .buf .writeString (badPrecString )
}
afterIndex = false
} else {
p .fmt .prec , p .fmt .precPresent , i = parsenum (format , i , end )
if !p .fmt .precPresent {
p .fmt .prec = 0
p .fmt .precPresent = true
}
}
}
if !afterIndex {
argNum , i , afterIndex = p .argNumber (argNum , format , i , len (a ))
}
if i >= end {
p .buf .writeString (noVerbString )
break
}
verb , size := rune (format [i ]), 1
if verb >= utf8 .RuneSelf {
verb , size = utf8 .DecodeRuneInString (format [i :])
}
i += size
switch {
case verb == '%' :
p .buf .writeByte ('%' )
case !p .goodArgNum :
p .badArgNum (verb )
case argNum >= len (a ):
p .missingArg (verb )
case verb == 'w' :
p .wrappedErrs = append (p .wrappedErrs , argNum )
fallthrough
case verb == 'v' :
p .fmt .sharpV = p .fmt .sharp
p .fmt .sharp = false
p .fmt .plusV = p .fmt .plus
p .fmt .plus = false
fallthrough
default :
p .printArg (a [argNum ], verb )
argNum ++
}
}
if !p .reordered && argNum < len (a ) {
p .fmt .clearflags ()
p .buf .writeString (extraString )
for i , arg := range a [argNum :] {
if i > 0 {
p .buf .writeString (commaSpaceString )
}
if arg == nil {
p .buf .writeString (nilAngleString )
} else {
p .buf .writeString (reflect .TypeOf (arg ).String ())
p .buf .writeByte ('=' )
p .printArg (arg , 'v' )
}
}
p .buf .writeByte (')' )
}
}
func (p *pp ) doPrint (a []any ) {
prevString := false
for argNum , arg := range a {
isString := arg != nil && reflect .TypeOf (arg ).Kind () == reflect .String
if argNum > 0 && !isString && !prevString {
p .buf .writeByte (' ' )
}
p .printArg (arg , 'v' )
prevString = isString
}
}
func (p *pp ) doPrintln (a []any ) {
for argNum , arg := range a {
if argNum > 0 {
p .buf .writeByte (' ' )
}
p .printArg (arg , 'v' )
}
p .buf .writeByte ('\n' )
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .