1. // Copyright 2009 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.
  4.  
  5. package fmt
  6.  
  7. import (
  8. "errors"
  9. "io"
  10. "os"
  11. "reflect"
  12. "sync"
  13. "unicode/utf8"
  14. )
  15.  
  16. // 用于 buffer.WriteString 的字符串,比使用 buffer.Write 写入字节数组更节省开销。
  17. const (
  18. commaSpaceString = ", "
  19. nilAngleString = "<nil>"
  20. nilParenString = "(nil)"
  21. nilString = "nil"
  22. mapString = "map["
  23. percentBangString = "%!"
  24. missingString = "(MISSING)"
  25. badIndexString = "(BADINDEX)"
  26. panicString = "(PANIC="
  27. extraString = "%!(EXTRA "
  28. badWidthString = "%!(BADWIDTH)"
  29. badPrecString = "%!(BADPREC)"
  30. noVerbString = "%!(NOVERB)"
  31. invReflectString = "<invalid reflect.Value>"
  32. )
  33.  
  34. // State 提供格式化器的相关信息,传递给 Formatter 使用
  35. type State interface {
  36. // 将格式化后的数据写入缓冲区中准备打印
  37. Write(b []byte) (n int, err error)
  38. // 返回宽度信息及其是否被设置
  39. Width() (wid int, ok bool)
  40. // 返回精度信息及其是否被设置
  41. Precision() (prec int, ok bool)
  42. // 返回旗标 [+- 0#] 是否被设置
  43. Flag(c int) bool
  44. }
  45.  
  46. // Formatter 用于让自定义类型实现自己的格式化过程。
  47. // Format 方法会被格式化器调用,只要对应的 arg 实现了该方法。
  48. // f 是格式化器的当前状态,c 是占位符中指定的动词。
  49. // 可以通过 f.Width 和 f.Precision 获取占位符中的宽度和精度信息
  50. // 可以通过 f.Flag(c) 判断占位符中是否设置了某个旗标(+- 0#)
  51. // 格式化后的结果通过 f.Write 写回去。
  52. type Formatter interface {
  53. Format(f State, c rune)
  54. }
  55.  
  56. // 格式化器在格式化某值的本地字符串时,会调用其类型的 String 方法。
  57. type Stringer interface {
  58. String() string
  59. }
  60.  
  61. // 格式化器在格式化某值的 Go 语法字符串(%#v)时,会调用其类型的 GoString 方法。
  62. type GoStringer interface {
  63. GoString() string
  64. }
  65.  
  66. // 使用简单的 []byte 代替 bytes.Buffer 避免大的依赖。
  67. type buffer []byte
  68.  
  69. func (b *buffer) Write(p []byte) {
  70. *b = append(*b, p...)
  71. }
  72.  
  73. func (b *buffer) WriteString(s string) {
  74. *b = append(*b, s...)
  75. }
  76.  
  77. func (b *buffer) WriteByte(c byte) {
  78. *b = append(*b, c)
  79. }
  80.  
  81. func (bp *buffer) WriteRune(r rune) {
  82. // 单字节 UTF8 字符快速处理
  83. if r < utf8.RuneSelf {
  84. *bp = append(*bp, byte(r))
  85. return
  86. }
  87. b := *bp
  88. // 准备缓冲区空间,用于写入 rune 编码
  89. n := len(b)
  90. for n+utf8.UTFMax > cap(b) {
  91. b = append(b, 0)
  92. }
  93. // 写入 rune 字符(必须提供足够的空间)
  94. w := utf8.EncodeRune(b[n:n+utf8.UTFMax], r)
  95. // 截断无效部分
  96. *bp = b[:n+w]
  97. }
  98.  
  99. // pp 是格式化器,整个格式化过程都是由它完成的。
  100. // 格式化结果将写入缓冲区 buf 中。
  101. type pp struct {
  102. // 存放结果的缓冲区 []byte
  103. buf buffer
  104.  
  105. // 当前需要格式化的参数
  106. arg interface{}
  107.  
  108. // 用于代替 arg,有反射值的时候就不用 arg 了
  109. value reflect.Value
  110.  
  111. // fmt 用于格式化基础类型
  112. // fmt 在 format.go 中定义
  113. fmt fmt
  114.  
  115. // 是否使用了自定义的 argNum(argNum 是正在处理的 arg 的序号)。
  116. reordered bool
  117. // 当前 argNum 是否合法(比如自定义 argNum 格式错误,或 argNum 超出范围)。
  118. goodArgNum bool
  119. // 用在 catchPanic 方法中,避免无限的“恐慌->恢复->恐慌->恢复...”递归情况。
  120. panicking bool
  121. // 当打印一个错误“动词”时设置 erroring,以防止调用 handleMethods。
  122. // 错误的“动词”不能用自定义方法去处理。
  123. erroring bool
  124. }
  125.  
  126. // 临时对象池
  127. var ppFree = sync.Pool{
  128. New: func() interface{} { return new(pp) },
  129. }
  130.  
  131. // 分配一个新的格式化器,或从临时对象池中取出一个。
  132. func newPrinter() *pp {
  133. p := ppFree.Get().(*pp)
  134. p.panicking = false
  135. p.erroring = false
  136. p.fmt.init(&p.buf)
  137. return p
  138. }
  139.  
  140. // 将用过的格式化器存入临时对象池中,避免每次调用时都重新分配内存。
  141. func (p *pp) free() {
  142. p.buf = p.buf[:0]
  143. p.arg = nil
  144. p.value = reflect.Value{}
  145. ppFree.Put(p)
  146. }
  147.  
  148. // 实现 State 接口
  149. func (p *pp) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent }
  150.  
  151. // 实现 State 接口
  152. func (p *pp) Precision() (prec int, ok bool) { return p.fmt.prec, p.fmt.precPresent }
  153.  
  154. // 实现 State 接口
  155. func (p *pp) Flag(b int) bool {
  156. switch b {
  157. case '-':
  158. return p.fmt.minus
  159. case '+':
  160. return p.fmt.plus || p.fmt.plusV
  161. case '#':
  162. return p.fmt.sharp || p.fmt.sharpV
  163. case ' ':
  164. return p.fmt.space
  165. case '0':
  166. return p.fmt.zero
  167. }
  168. return false
  169. }
  170.  
  171. // 实现 State 接口
  172. func (p *pp) Write(b []byte) (ret int, err error) {
  173. p.buf.Write(b)
  174. return len(b), nil
  175. }
  176.  
  177. // 这些函数以 f 结尾,并需要一个格式字符串。
  178.  
  179. // Fprintf 根据格式字符串 format 对 a 中提供的 arg 进行格式化,
  180. // 并将结果写入 w。返回写入的字节数和错误信息。
  181. func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
  182. p := newPrinter()
  183. p.doPrintf(format, a)
  184. n, err = w.Write(p.buf)
  185. p.free()
  186. return
  187. }
  188.  
  189. // Printf 根据格式字符串 format 对 a 中提供的 arg 进行格式化,
  190. // 并将结果写入标准输出。返回写入的字节数和错误信息。
  191. func Printf(format string, a ...interface{}) (n int, err error) {
  192. return Fprintf(os.Stdout, format, a...)
  193. }
  194.  
  195. // Sprintf 根据格式字符串 format 对 a 中提供的 arg 进行格式化,并返回结果。
  196. func Sprintf(format string, a ...interface{}) string {
  197. p := newPrinter()
  198. p.doPrintf(format, a)
  199. s := string(p.buf)
  200. p.free()
  201. return s
  202. }
  203.  
  204. // Errorf 根据格式字符串 format 对 a 中提供的 arg 进行格式化,
  205. // 并将结果包装成 error 类型返回。
  206. func Errorf(format string, a ...interface{}) error {
  207. return errors.New(Sprintf(format, a...))
  208. }
  209.  
  210. // 这些函数没有格式字符串
  211.  
  212. // Fprint 使用默认格式对 a 中提供的 arg 进行格式化,并将结果写入 w。
  213. // 返回写入的字节数和错误信息。
  214. // 非字符串 arg 之间会添加空格。
  215. func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
  216. p := newPrinter()
  217. p.doPrint(a)
  218. n, err = w.Write(p.buf)
  219. p.free()
  220. return
  221. }
  222.  
  223. // Print 使用默认格式对 a 中提供的 arg 进行格式化,并将结果写入到标准输出。
  224. // 返回写入的字节数和错误信息。
  225. // 非字符串 arg 之间会添加空格。
  226. func Print(a ...interface{}) (n int, err error) {
  227. return Fprint(os.Stdout, a...)
  228. }
  229.  
  230. // Sprint 使用默认格式对 a 中提供的 arg 进行格式化,并返回结果。
  231. // 非字符串 arg 之间会添加空格。
  232. func Sprint(a ...interface{}) string {
  233. p := newPrinter()
  234. p.doPrint(a)
  235. s := string(p.buf)
  236. p.free()
  237. return s
  238. }
  239.  
  240. // 这些函数以 ln 结尾,不需要格式字符串。
  241.  
  242. // Fprintln 使用默认格式对 a 中提供的 arg 进行格式化,并将结果写入 w。
  243. // 返回写入的字节数和错误信息。
  244. // 各 arg 之间会添加空格,并在最后添加换行符。
  245. func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
  246. p := newPrinter()
  247. p.doPrintln(a)
  248. n, err = w.Write(p.buf)
  249. p.free()
  250. return
  251. }
  252.  
  253. // Println 使用默认格式对 a 中提供的 arg 进行格式化,并将结果写入标准输出。
  254. // 返回写入的字节数和错误信息。
  255. // 各 arg 之间会添加空格,并在最后添加换行符。
  256. func Println(a ...interface{}) (n int, err error) {
  257. return Fprintln(os.Stdout, a...)
  258. }
  259.  
  260. // Sprintln 使用默认格式对 a 中提供的 arg 进行格式化,并返回结果。
  261. // 各 arg 之间会添加空格,并在最后添加换行符。
  262. func Sprintln(a ...interface{}) string {
  263. p := newPrinter()
  264. p.doPrintln(a)
  265. s := string(p.buf)
  266. p.free()
  267. return s
  268. }
  269.  
  270. // 获取结构体的第 i 个字段。如果字段自身是接口类型,
  271. // 则返回接口中的值,而不是接口自身。
  272. func getField(v reflect.Value, i int) reflect.Value {
  273. val := v.Field(i)
  274. if val.Kind() == reflect.Interface && !val.IsNil() {
  275. val = val.Elem()
  276. }
  277. return val
  278. }
  279.  
  280. // 判断整数值是否过大,超出格式化宽度和精度的允许范围。
  281. func tooLarge(x int) bool {
  282. const max int = 1e6
  283. return x > max || x < -max
  284. }
  285.  
  286. // 将字符串格式的数值尽可能解析为 int 型数值,直到遇到非数字字符为止。
  287. // 如果没有解析出任何数值,则 num 返回 0,且 isnum 返回 false。
  288. // newi 返回待处理下标(即:处理完开头的所有数字之后的下一个字符的下标)
  289. func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
  290. if start >= end {
  291. return 0, false, end
  292. }
  293. // 在“数字字符串”范围内循环,并计算结果
  294. for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ {
  295. if tooLarge(num) {
  296. return 0, false, end
  297. }
  298. num = num*10 + int(s[newi]-'0')
  299. isnum = true
  300. }
  301. return
  302. }
  303.  
  304. // 写入未知类型的值
  305. func (p *pp) unknownType(v reflect.Value) {
  306. if !v.IsValid() {
  307. p.buf.WriteString(nilAngleString)
  308. return
  309. }
  310. p.buf.WriteByte('?')
  311. p.buf.WriteString(v.Type().String())
  312. p.buf.WriteByte('?')
  313. }
  314.  
  315. // 处理无效动词(无法被指定类型识别的动词)。比如布尔型只能
  316. // 识别 v 和 t 两个动词,那么其它动词对布尔型来说就是无效动词。
  317. func (p *pp) badVerb(verb rune) {
  318. // 标记 erroring,防止调用 handleMethods 方法,
  319. // 因为无效动词不能交给类型自己去处理。
  320. p.erroring = true
  321. p.buf.WriteString(percentBangString) // "%!"
  322. p.buf.WriteRune(verb)
  323. p.buf.WriteByte('(')
  324. switch {
  325. case p.arg != nil:
  326. p.buf.WriteString(reflect.TypeOf(p.arg).String())
  327. p.buf.WriteByte('=')
  328. p.printArg(p.arg, 'v')
  329. case p.value.IsValid(): // (*int)(nil)
  330. p.buf.WriteString(p.value.Type().String())
  331. p.buf.WriteByte('=')
  332. p.printValue(p.value, 'v', 0)
  333. default:
  334. p.buf.WriteString(nilAngleString) // "<nil>"
  335. }
  336. p.buf.WriteByte(')')
  337. p.erroring = false
  338. }
  339.  
  340. // 写入布尔型值
  341. func (p *pp) fmtBool(v bool, verb rune) {
  342. switch verb {
  343. case 't', 'v':
  344. p.fmt.fmt_boolean(v)
  345. default:
  346. p.badVerb(verb)
  347. }
  348. }
  349.  
  350. // 写入整型值的十六进制格式
  351. // leading0x:是否添加 0x 前导符
  352. func (p *pp) fmt0x64(v uint64, leading0x bool) {
  353. // 通过临时设置 # 旗标来添加 0x 前导符
  354. sharp := p.fmt.sharp
  355. p.fmt.sharp = leading0x
  356. p.fmt.fmt_integer(v, 16, unsigned, ldigits)
  357. p.fmt.sharp = sharp
  358. }
  359.  
  360. // 写入整型值,包有符号和无符号
  361. func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) {
  362. switch verb {
  363. case 'v': // 十进制
  364. if p.fmt.sharpV && !isSigned { // Go 语法格式:无符号型用 0xFF 格式
  365. p.fmt0x64(v, true)
  366. } else {
  367. p.fmt.fmt_integer(v, 10, isSigned, ldigits)
  368. }
  369. case 'd': // 十进制
  370. p.fmt.fmt_integer(v, 10, isSigned, ldigits)
  371. case 'b': // 二进制
  372. p.fmt.fmt_integer(v, 2, isSigned, ldigits)
  373. case 'o': // 八进制
  374. p.fmt.fmt_integer(v, 8, isSigned, ldigits)
  375. case 'x': // 十六进制(小写)
  376. p.fmt.fmt_integer(v, 16, isSigned, ldigits)
  377. case 'X': // 十六进制(大写)
  378. p.fmt.fmt_integer(v, 16, isSigned, udigits)
  379. case 'c': // 字符
  380. p.fmt.fmt_c(v)
  381. case 'q': // '字符'
  382. if v <= utf8.MaxRune {
  383. p.fmt.fmt_qc(v)
  384. } else {
  385. p.badVerb(verb)
  386. }
  387. case 'U': // U+FFFF
  388. p.fmt.fmt_unicode(v)
  389. default:
  390. p.badVerb(verb)
  391. }
  392. }
  393.  
  394. // 写入浮点型值
  395. func (p *pp) fmtFloat(v float64, size int, verb rune) {
  396. // fmt_float 的最后一个参数指定精度
  397. switch verb {
  398. case 'v':
  399. p.fmt.fmt_float(v, size, 'g', -1)
  400. case 'b', 'g', 'G':
  401. p.fmt.fmt_float(v, size, verb, -1)
  402. case 'f', 'e', 'E':
  403. p.fmt.fmt_float(v, size, verb, 6)
  404. case 'F':
  405. p.fmt.fmt_float(v, size, 'f', 6)
  406. default:
  407. p.badVerb(verb)
  408. }
  409. }
  410.  
  411. // 写入复数型值
  412. // 将实部和虚部用 fmtFloat 分别格式化后写入缓冲区。
  413. func (p *pp) fmtComplex(v complex128, size int, verb rune) {
  414. switch verb {
  415. case 'v', 'b', 'g', 'G', 'f', 'F', 'e', 'E':
  416. oldPlus := p.fmt.plus
  417. p.buf.WriteByte('(')
  418. p.fmtFloat(real(v), size/2, verb)
  419. // 虚部总有一个符号
  420. p.fmt.plus = true
  421. p.fmtFloat(imag(v), size/2, verb)
  422. p.buf.WriteString("i)")
  423. p.fmt.plus = oldPlus
  424. default:
  425. p.badVerb(verb)
  426. }
  427. }
  428.  
  429. // 写入字符串
  430. func (p *pp) fmtString(v string, verb rune) {
  431. switch verb {
  432. case 'v': // 字符串(无引号)
  433. if p.fmt.sharpV { // Go 语法格式:字符串(有引号)
  434. p.fmt.fmt_q(v)
  435. } else {
  436. p.fmt.fmt_s(v)
  437. }
  438. case 's': // 字符串(无引号)
  439. p.fmt.fmt_s(v)
  440. case 'x': // 十六进制字符串(小写)
  441. p.fmt.fmt_sx(v, ldigits)
  442. case 'X': // 十六进制字符串(大写)
  443. p.fmt.fmt_sx(v, udigits)
  444. case 'q': // 字符串(有引号)
  445. p.fmt.fmt_q(v)
  446. default:
  447. p.badVerb(verb)
  448. }
  449. }
  450.  
  451. // 写入字节切片型
  452. func (p *pp) fmtBytes(v []byte, verb rune, typeString string) {
  453. switch verb {
  454. case 'v', 'd': // [元素 元素 ...]
  455. if p.fmt.sharpV { // Go 语法格式:[]byte{0xFF, 0xFF, ...}
  456. p.buf.WriteString(typeString)
  457. if v == nil {
  458. p.buf.WriteString(nilParenString) // "(nil)"
  459. return
  460. }
  461. p.buf.WriteByte('{')
  462. for i, c := range v {
  463. if i > 0 { // 第一个元素前面不添加分隔符
  464. p.buf.WriteString(commaSpaceString) // ", "
  465. }
  466. p.fmt0x64(uint64(c), true)
  467. }
  468. p.buf.WriteByte('}')
  469. } else {
  470. p.buf.WriteByte('[')
  471. for i, c := range v {
  472. if i > 0 { // 第一个元素前面不添加分隔符
  473. p.buf.WriteByte(' ')
  474. }
  475. p.fmt.fmt_integer(uint64(c), 10, unsigned, ldigits)
  476. }
  477. p.buf.WriteByte(']')
  478. }
  479. case 's': // 字符串(无引号)
  480. p.fmt.fmt_s(string(v))
  481. case 'x': // 十六进制字符串(小写)
  482. p.fmt.fmt_bx(v, ldigits)
  483. case 'X': // 十六进制字符串(大写)
  484. p.fmt.fmt_bx(v, udigits)
  485. case 'q': // 字符串(有引号)
  486. p.fmt.fmt_q(string(v))
  487. default:
  488. p.printValue(reflect.ValueOf(v), verb, 0)
  489. }
  490. }
  491.  
  492. // 写入指针
  493. func (p *pp) fmtPointer(value reflect.Value, verb rune) {
  494. var u uintptr
  495. // 只接受指定类型的值并转换为指针:通道、函数、映射、指针、切片、非安全指针
  496. switch value.Kind() {
  497. case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
  498. u = value.Pointer()
  499. default:
  500. p.badVerb(verb)
  501. return
  502. }
  503.  
  504. switch verb {
  505. case 'v': // 0xffffffffff(或 "nil")
  506. if p.fmt.sharpV { // Go 语法格式:(类型)(0xffffffffff)
  507. p.buf.WriteByte('(')
  508. p.buf.WriteString(value.Type().String())
  509. p.buf.WriteString(")(")
  510. if u == 0 {
  511. p.buf.WriteString(nilString) // "nil"
  512. } else {
  513. p.fmt0x64(uint64(u), true)
  514. }
  515. p.buf.WriteByte(')')
  516. } else {
  517. if u == 0 {
  518. p.fmt.padString(nilAngleString) // <"nil">
  519. } else {
  520. p.fmt0x64(uint64(u), !p.fmt.sharp)
  521. }
  522. }
  523. case 'p': // 0xffffffffff
  524. p.fmt0x64(uint64(u), !p.fmt.sharp)
  525. case 'b', 'o', 'd', 'x', 'X': // 当整数处理
  526. p.fmtInteger(uint64(u), unsigned, verb)
  527. default:
  528. p.badVerb(verb)
  529. }
  530. }
  531.  
  532. // 用在 handleMethods 方法中,捕捉自定义类型的格式化方法中产生的恐慌。
  533. func (p *pp) catchPanic(arg interface{}, verb rune) {
  534. if err := recover(); err != nil {
  535. // 如果 arg 是一个 nil,只需要写入 "<nil>" 即可。出现这种 panic 最有
  536. // 可能的原因是 Stringer 未能防止无效的 nil 或以 nil 做为接收器。无论
  537. // 哪种情况,写入 "<nil>" 是一个很好的选择。
  538. if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() {
  539. p.buf.WriteString(nilAngleString)
  540. return
  541. }
  542. // 否则通过后面的一系列语句打印一个简明的 panic 信息即可。
  543. if p.panicking {
  544. // 如果后面的 printArg 中又产生了 panic,那么真的就恐慌了。
  545. panic(err)
  546. }
  547. p.fmt.clearflags() // 一个占位符算处理完了,进行复位。
  548. p.buf.WriteString(percentBangString)
  549. p.buf.WriteRune(verb)
  550. p.buf.WriteString(panicString)
  551. p.panicking = true // 防止“恐慌 -> 恢复 -> 恐慌 -> 恢复”无限递归
  552. p.printArg(err, 'v')
  553. p.panicking = false
  554. p.buf.WriteByte(')')
  555. }
  556. }
  557.  
  558. // 判断 p.arg 是否有自定义的格式化方法,如果有就调用,如果没有,就返回 false。
  559. func (p *pp) handleMethods(verb rune) (handled bool) {
  560. // 如果正在处理无效动词,则不使用自定义方法。
  561. if p.erroring {
  562. return
  563. }
  564. // 实现了 Format 方法
  565. if formatter, ok := p.arg.(Formatter); ok {
  566. // 标记 p.arg 已经处理了。
  567. handled = true
  568. // 捕捉 Format() 中产生的恐慌
  569. defer p.catchPanic(p.arg, verb)
  570. // 处理 arg
  571. formatter.Format(p, verb)
  572. return
  573. }
  574. // 要求 Go 语法格式
  575. if p.fmt.sharpV {
  576. // 实现了 GoString 方法
  577. if stringer, ok := p.arg.(GoStringer); ok {
  578. handled = true
  579. // 捕捉 GoString() 中产生的恐慌
  580. defer p.catchPanic(p.arg, verb)
  581. // 处理 arg
  582. p.fmt.fmt_s(stringer.GoString())
  583. return
  584. }
  585. } else {
  586. // 如果指定了字符串相关的动词,则判断 p.arg 可否转换为字符串
  587. switch verb {
  588. case 'v', 's', 'x', 'X', 'q':
  589. switch v := p.arg.(type) {
  590. case error: // Error() 方法可以获取到字符串
  591. handled = true
  592. // 捕捉 Error() 中产生的恐慌
  593. defer p.catchPanic(p.arg, verb)
  594. // 处理 arg
  595. p.fmtString(v.Error(), verb)
  596. return
  597.  
  598. case Stringer: // String() 方法可以获取到字符串
  599. handled = true
  600. // 捕捉 String() 中产生的恐慌
  601. defer p.catchPanic(p.arg, verb)
  602. // 处理 arg
  603. p.fmtString(v.String(), verb)
  604. return
  605. }
  606. }
  607. }
  608. return false
  609. }
  610.  
  611. // printArg 只处理非嵌套的基础类型,其它类型的 arg,则交给 printValue 进行
  612. // 反射处理。如果 arg 有自定义的格式化方法,则 printArg 会调用自定义方法进行处理。
  613. // 对于嵌套中的类型,也是交给 printValue 进行处理。
  614. func (p *pp) printArg(arg interface{}, verb rune) {
  615. // 记下当前 arg 内容,方便其它地方使用
  616. p.arg = arg
  617. // 初始化为零值,防止其它地方调用了 nil
  618. p.value = reflect.Value{}
  619.  
  620. if arg == nil {
  621. switch verb {
  622. case 'T', 'v':
  623. p.fmt.padString(nilAngleString) // "<nil>"
  624. default:
  625. p.badVerb(verb)
  626. }
  627. return
  628. }
  629.  
  630. // %T(类型)和 %p(指针)是特殊动词,需要优先处理。
  631. switch verb {
  632. case 'T':
  633. p.fmt.fmt_s(reflect.TypeOf(arg).String())
  634. return
  635. case 'p':
  636. p.fmtPointer(reflect.ValueOf(arg), 'p')
  637. return
  638. }
  639.  
  640. // 简单类型可以不用反射处理,直接调用相应的处理函数即可。
  641. switch f := arg.(type) {
  642. case bool:
  643. p.fmtBool(f, verb)
  644. case float32:
  645. p.fmtFloat(float64(f), 32, verb)
  646. case float64:
  647. p.fmtFloat(f, 64, verb)
  648. case complex64:
  649. p.fmtComplex(complex128(f), 64, verb)
  650. case complex128:
  651. p.fmtComplex(f, 128, verb)
  652. case int:
  653. p.fmtInteger(uint64(f), signed, verb)
  654. case int8:
  655. p.fmtInteger(uint64(f), signed, verb)
  656. case int16:
  657. p.fmtInteger(uint64(f), signed, verb)
  658. case int32:
  659. p.fmtInteger(uint64(f), signed, verb)
  660. case int64:
  661. p.fmtInteger(uint64(f), signed, verb)
  662. case uint:
  663. p.fmtInteger(uint64(f), unsigned, verb)
  664. case uint8:
  665. p.fmtInteger(uint64(f), unsigned, verb)
  666. case uint16:
  667. p.fmtInteger(uint64(f), unsigned, verb)
  668. case uint32:
  669. p.fmtInteger(uint64(f), unsigned, verb)
  670. case uint64:
  671. p.fmtInteger(f, unsigned, verb)
  672. case uintptr:
  673. p.fmtInteger(uint64(f), unsigned, verb)
  674. case string:
  675. p.fmtString(f, verb)
  676. case []byte:
  677. p.fmtBytes(f, verb, "[]byte")
  678. case reflect.Value:
  679. p.printValue(f, verb, 0)
  680. default:
  681. // 其它类型可能有自定义的格式化方法,在这里调用。
  682. if !p.handleMethods(verb) {
  683. // 如果该类型没有可用于格式化的方法,则通过反射处理。
  684. p.printValue(reflect.ValueOf(f), verb, 0)
  685. }
  686. }
  687. }
  688.  
  689. var byteType = reflect.TypeOf(byte(0))
  690.  
  691. // printValue 类似于 printArg 但是以反射值作为参数,而不是接口值。
  692. // 它不处理 'p' 和 'T' 动词,因为这些已经被 printArg 处理过了。
  693. // depth 表示嵌套深度,比如结构体中嵌套的类型,其深度就大于 0。
  694. func (p *pp) printValue(value reflect.Value, verb rune, depth int) {
  695. // 嵌套中的值,即使有自定义的格式化方法,也不会被 printArg 调用,在这里进行调用
  696. if depth > 0 && value.IsValid() && value.CanInterface() {
  697. p.arg = value.Interface()
  698. if p.handleMethods(verb) {
  699. return
  700. }
  701. }
  702. p.arg = nil // 传入的是反射值,反射值不一定是通过 arg 获取到的,清空防干扰
  703. p.value = value // 记下 value 内容,方便其它地方使用
  704.  
  705. switch f := value; value.Kind() {
  706. case reflect.Invalid:
  707. if depth == 0 { // 非嵌套的无效值
  708. p.buf.WriteString(invReflectString) // "<invalid reflect.Value>"
  709. } else { // 嵌套的无效值
  710. switch verb {
  711. case 'v':
  712. p.buf.WriteString(nilAngleString) // "<nil>"
  713. default:
  714. p.badVerb(verb)
  715. }
  716. }
  717. // 不同类型的处理方法和 printArg 中相同。
  718. case reflect.Bool:
  719. p.fmtBool(f.Bool(), verb)
  720. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  721. p.fmtInteger(uint64(f.Int()), signed, verb)
  722. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  723. p.fmtInteger(f.Uint(), unsigned, verb)
  724. case reflect.Float32:
  725. p.fmtFloat(f.Float(), 32, verb)
  726. case reflect.Float64:
  727. p.fmtFloat(f.Float(), 64, verb)
  728. case reflect.Complex64:
  729. p.fmtComplex(f.Complex(), 64, verb)
  730. case reflect.Complex128:
  731. p.fmtComplex(f.Complex(), 128, verb)
  732. case reflect.String:
  733. p.fmtString(f.String(), verb)
  734. // 嵌套类型 map,需要递归
  735. case reflect.Map:
  736. if p.fmt.sharpV { // Go 语法格式
  737. p.buf.WriteString(f.Type().String())
  738. if f.IsNil() {
  739. p.buf.WriteString(nilParenString) // "(nil)"
  740. return
  741. }
  742. p.buf.WriteByte('{')
  743. } else {
  744. p.buf.WriteString(mapString) // "map["
  745. }
  746. keys := f.MapKeys()
  747. for i, key := range keys {
  748. if i > 0 { // 第一个元素前面不添加分隔符
  749. if p.fmt.sharpV { // Go 语法格式
  750. p.buf.WriteString(commaSpaceString) // ", "
  751. } else {
  752. p.buf.WriteByte(' ')
  753. }
  754. }
  755. p.printValue(key, verb, depth+1) // 递归处理键
  756. p.buf.WriteByte(':')
  757. p.printValue(f.MapIndex(key), verb, depth+1) // 递归处理值
  758. }
  759. if p.fmt.sharpV { // Go 语法格式
  760. p.buf.WriteByte('}')
  761. } else {
  762. p.buf.WriteByte(']')
  763. }
  764. // 嵌套类型 struct,需要递归
  765. case reflect.Struct:
  766. if p.fmt.sharpV { // Go 语法格式
  767. p.buf.WriteString(f.Type().String())
  768. }
  769. p.buf.WriteByte('{')
  770. for i := 0; i < f.NumField(); i++ {
  771. if i > 0 { // 第一个元素前面不添加分隔符
  772. if p.fmt.sharpV { // Go 语法格式
  773. p.buf.WriteString(commaSpaceString) // ", "
  774. } else {
  775. p.buf.WriteByte(' ')
  776. }
  777. }
  778. // 结构体字段语法格式 || Go 语法格式(类型:值)
  779. if p.fmt.plusV || p.fmt.sharpV {
  780. if name := f.Type().Field(i).Name; name != "" {
  781. p.buf.WriteString(name)
  782. p.buf.WriteByte(':')
  783. }
  784. }
  785. // 递归处理成员
  786. p.printValue(getField(f, i), verb, depth+1)
  787. }
  788. p.buf.WriteByte('}')
  789. // 接口(包含实现该接口的对象),需要递归
  790. case reflect.Interface:
  791. value := f.Elem() // 获取接口中的对象
  792. if !value.IsValid() {
  793. if p.fmt.sharpV { // Go 语法格式
  794. p.buf.WriteString(f.Type().String())
  795. p.buf.WriteString(nilParenString) // "(nil)"
  796. } else {
  797. p.buf.WriteString(nilAngleString) // "<nil>"
  798. }
  799. } else {
  800. // 递归处理接口中的对象
  801. p.printValue(value, verb, depth+1)
  802. }
  803. // 嵌套类型 map、slice,可能需要递归(如果元素不是字节的话)
  804. case reflect.Array, reflect.Slice:
  805. switch verb {
  806. case 's', 'q', 'x', 'X':
  807. // 处理字节类型的切片和数组,它们对于上面的动词而言比较特殊,不用递归。
  808. t := f.Type()
  809. if t.Elem().Kind() == reflect.Uint8 { // 判断元素类型
  810. var bytes []byte
  811. if f.Kind() == reflect.Slice { // 切片类型(直接获取字节内容)
  812. bytes = f.Bytes()
  813. } else if f.CanAddr() { // 可以转换成切片
  814. bytes = f.Slice(0, f.Len()).Bytes()
  815. } else { // 不能转换为切片
  816. // 数组不能 Slice(),所以手动建立了一个切片,这是一种罕见的情况。
  817. bytes = make([]byte, f.Len())
  818. for i := range bytes {
  819. bytes[i] = byte(f.Index(i).Uint())
  820. }
  821. }
  822. // 写入获取到的字节内容
  823. p.fmtBytes(bytes, verb, t.String())
  824. return
  825. }
  826. }
  827. if p.fmt.sharpV { // Go 语法格式
  828. p.buf.WriteString(f.Type().String())
  829. if f.Kind() == reflect.Slice && f.IsNil() {
  830. p.buf.WriteString(nilParenString) // "(nil)"
  831. return
  832. } else {
  833. p.buf.WriteByte('{')
  834. for i := 0; i < f.Len(); i++ {
  835. if i > 0 { // 第一个元素前面不添加分隔符
  836. p.buf.WriteString(commaSpaceString) // ", "
  837. }
  838. // 递归处理元素
  839. p.printValue(f.Index(i), verb, depth+1)
  840. }
  841. p.buf.WriteByte('}')
  842. }
  843. } else {
  844. p.buf.WriteByte('[')
  845. for i := 0; i < f.Len(); i++ {
  846. if i > 0 { // 第一个元素前面不添加分隔符
  847. p.buf.WriteByte(' ')
  848. }
  849. // 递归处理元素
  850. p.printValue(f.Index(i), verb, depth+1)
  851. }
  852. p.buf.WriteByte(']')
  853. }
  854. // 指针(指向具体的对象),需要递归
  855. case reflect.Ptr:
  856. // 只处理最外层的指针,不处理嵌套中的指针(避免循环)
  857. if depth == 0 && f.Pointer() != 0 {
  858. // 获取指针指向的元素
  859. switch a := f.Elem(); a.Kind() {
  860. // 数组、切片、结构、映射
  861. case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map:
  862. p.buf.WriteByte('&')
  863. // 递归处理指针指向的元素
  864. p.printValue(a, verb, depth+1)
  865. return
  866. }
  867. }
  868. // 嵌套指针交给下面的代码处理
  869. fallthrough
  870. // 通道、函数、不安全指针,只写入指针地址。
  871. case reflect.Chan, reflect.Func, reflect.UnsafePointer:
  872. p.fmtPointer(f, verb)
  873. default:
  874. p.unknownType(f)
  875. }
  876. }
  877.  
  878. // 之后的代码用于解析格式字符串中的“占位符”
  879.  
  880. // 从指定 arg 中读取整数值(用于提供给精度或宽度)。
  881. // a:arg 列表。argNum:要获取的 arg 下标
  882. // num:获取到的值。isInt:arg 是否为整型。
  883. // newArgNum:成功则返回 argNum+1,失败则返回 argNum。
  884. func intFromArg(a []interface{}, argNum int) (num int, isInt bool, newArgNum int) {
  885. newArgNum = argNum
  886. if argNum < len(a) {
  887. num, isInt = a[argNum].(int) // 通常这里都会转换成功,从而跳过下面一大堆代码。
  888. if !isInt {
  889. switch v := reflect.ValueOf(a[argNum]); v.Kind() {
  890. // 有符号整型
  891. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  892. n := v.Int()
  893. // 根据平台的不同,在 int 范围内进行判断
  894. if int64(int(n)) == n {
  895. num = int(n)
  896. isInt = true
  897. }
  898. // 无符号整型
  899. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  900. n := v.Uint()
  901. // 根据平台的不同,在 int 范围内进行判断
  902. if int64(n) >= 0 && uint64(int(n)) == n {
  903. num = int(n)
  904. isInt = true
  905. }
  906. default:
  907. // 默认值 num = 0, isInt = false.
  908. }
  909. }
  910. newArgNum = argNum + 1
  911. // 范围检查
  912. if tooLarge(num) {
  913. num = 0
  914. isInt = false
  915. }
  916. }
  917. return
  918. }
  919.  
  920. // 解析 arg 索引,将 [] 中的字符串解析成数值再减 1 后返回。
  921. // format 必须以“[”开头,“]”的位置则会通过查找确定。
  922. // 因为 arg 索引是从 1 开始的,而 arg 下标则是从 0 开始的,所以要减 1。
  923. // index:解析结果。wid:索引字符串的总长度(包括中括号)。ok:是否成功。
  924. // 如果 [] 为空或没有结束括号“]”,则解析失败,index 无效,wid 返回 1。
  925. // wid 返回 1 表示跳过无效的起始括号“[”,继续处理之后的内容。
  926. // 如果 [] 中的内容不全是数字,则解析失败,index 无效,wid 正常返回。
  927. func parseArgNumber(format string) (index int, wid int, ok bool) {
  928. // 长度至少 3 个字节: [n]。
  929. if len(format) < 3 {
  930. return 0, 1, false
  931. }
  932.  
  933. // 查找结束括号“]”
  934. for i := 1; i < len(format); i++ {
  935. if format[i] == ']' {
  936. // 解析 [] 之间的内容。
  937. // width:解析结果。ok:是否解析成功。newi:待处理下标
  938. width, ok, newi := parsenum(format, 1, i)
  939. // 解析失败,或者 n 中含有非法字符。
  940. if !ok || newi != i {
  941. return 0, i + 1, false
  942. }
  943. // 解析成功
  944. return width - 1, i + 1, true
  945. }
  946. }
  947. // 没有结束括号“]”
  948. return 0, 1, false
  949. }
  950.  
  951. // 解析 format 中的一个 arg 索引,i 标识索引字符串的起始位置,
  952. // 解析过程是通过 parseArgNumber 完成的,这里只进行一些检查、控制等操作。
  953. // argNum:要解析的 arg 下标。numArgs:arg 总个数。
  954. // newArgNum:解析结果。newi:待处理下标。found:是否找到 [] 并且中间全是数字。
  955. func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) {
  956. // format[i] 必须是“[”字符,否则按原值返回,不予处理
  957. if len(format) <= i || format[i] != '[' {
  958. return argNum, i, false
  959. }
  960. // 标记使用了指定的 argNum,原 argNum 的顺序被打乱。
  961. p.reordered = true
  962. // 调用另一个函数去处理 arg 索引
  963. index, wid, ok := parseArgNumber(format[i:])
  964. // 解析成功,并且解析出来的 arg 索引在合法范围内。
  965. if ok && 0 <= index && index < numArgs {
  966. return index, i + wid, true
  967. }
  968. // 解析失败,或者解析出来的 arg 索引超出合法范围。
  969. // 标记当前 arg 索引无效
  970. p.goodArgNum = false
  971. // ok 可能为 true(比如结果超出范围,但这符合 found 的要求)
  972. return argNum, i + wid, ok
  973. }
  974.  
  975. // 无效arg索引
  976. func (p *pp) badArgNum(verb rune) {
  977. p.buf.WriteString(percentBangString) // "%!"
  978. p.buf.WriteRune(verb)
  979. p.buf.WriteString(badIndexString) // "(BADINDEX)"
  980. }
  981.  
  982. // 未找到相应arg
  983. func (p *pp) missingArg(verb rune) {
  984. p.buf.WriteString(percentBangString) // "%!"
  985. p.buf.WriteRune(verb)
  986. p.buf.WriteString(missingString) // "(MISSING)"
  987. }
  988.  
  989. // 解析占位符并格式化相应 arg,以替换占位符。
  990. func (p *pp) doPrintf(format string, a []interface{}) {
  991. end := len(format) // 用于范围检查
  992. argNum := 0 // 正在处理的 arg 索引
  993. afterIndex := false // 是否刚处理完占位符中的 [n]
  994. p.reordered = false // 当前 argNum 是否由占位符中 [n] 指定
  995. formatLoop:
  996. // 每循环一次,处理一个占位符。
  997. for i := 0; i < end; {
  998. // 复位有效性,新的 argNum 是有效的
  999. p.goodArgNum = true
  1000.  
  1001. // 1、写入 % 之前的内容
  1002.  
  1003. lasti := i
  1004. for i < end && format[i] != '%' {
  1005. i++
  1006. }
  1007. if i > lasti {
  1008. p.buf.WriteString(format[lasti:i])
  1009. }
  1010. // 如果到达尾部,则所有占位符都处理完毕,返回
  1011. if i >= end {
  1012. break
  1013. }
  1014.  
  1015. // 跳过 % 字符,正式进入一个“占位符”的处理流程
  1016. i++
  1017.  
  1018. // 复位旗标,准备重新登记
  1019. p.fmt.clearflags()
  1020. simpleFormat:
  1021.  
  1022. // 2、处理旗标 [#0+- ]
  1023.  
  1024. for ; i < end; i++ {
  1025. c := format[i]
  1026. switch c {
  1027. case '#':
  1028. p.fmt.sharp = true
  1029. case '0':
  1030. // 0 只允许填充在左边(不能与 "-" 共存)
  1031. p.fmt.zero = !p.fmt.minus // "-" 优先于 "0"
  1032. case '+':
  1033. p.fmt.plus = true
  1034. case '-':
  1035. // 0 只允许填充在左边(不能与 "-" 共存)
  1036. p.fmt.minus = true
  1037. p.fmt.zero = false // "-" 优先于 "0"
  1038. case ' ':
  1039. p.fmt.space = true
  1040. default:
  1041. // 没有指定“精度、宽度、[n]”的简单占位符,可以在这里快速处理。
  1042. // 这是常见的占位符,单独处理可以提高效率。
  1043. if 'a' <= c && c <= 'z' && argNum < len(a) {
  1044. if c == 'v' {
  1045. p.fmt.sharpV = p.fmt.sharp // Go 语法格式 #v
  1046. p.fmt.sharp = false // # 不再具有默认的含义
  1047. p.fmt.plusV = p.fmt.plus // 结构体字段语法格式 +v
  1048. p.fmt.plus = false // + 不再具有默认的含义
  1049. }
  1050. p.printArg(a[argNum], rune(c)) // 分析完毕,处理当前 arg
  1051. argNum++ // 准备处理下一个 arg
  1052. i++ // 跳过刚处理的动词
  1053. continue formatLoop // 继续处理下一个占位符
  1054. }
  1055. // 更复杂的占位符(交给后面的代码继续分析)
  1056. break simpleFormat
  1057. }
  1058. }
  1059.  
  1060. // 旗标已经处理过了,接下来处理占位符中的 [n]、宽度、精度信息
  1061.  
  1062. // 处理 [n](这里处理 [n] 是为后面处理 [n]* 宽度信息做准备,
  1063. // 因为要从相应的 arg 中读取宽度值)
  1064. argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
  1065. // argNum:获取到的 [n] 中的值。i:待处理下标。
  1066. // afterIndex:是否刚处理完 [n]
  1067.  
  1068. // 处理从 arg 中获取的宽度信息 *
  1069. // * 表示用 args[argNum] 的值作为宽度值来格式化 args[argNum+1]
  1070. if i < end && format[i] == '*' {
  1071. i++ // 跳过 * 号
  1072.  
  1073. // wid:args[argNum] 的值。widPresent:wid 是否设置成功。
  1074. // argNum:argNum+1(无论 wid 是否设置成功,只要不超出 args 数量)
  1075. p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum)
  1076.  
  1077. // 宽度值设置失败,处理无效宽度(仅显示一个提示,不影响其它部分的处理)
  1078. if !p.fmt.widPresent {
  1079. p.buf.WriteString(badWidthString) // "%!(BADWIDTH)"
  1080. }
  1081.  
  1082. // 处理获取到的负宽度值,将其转换为正数,并设置 "-" 旗标为 true
  1083. if p.fmt.wid < 0 {
  1084. p.fmt.wid = -p.fmt.wid
  1085. p.fmt.minus = true
  1086. p.fmt.zero = false // 0 只允许填充在左边(不能与 "-" 共存)
  1087. }
  1088. afterIndex = false // 刚处理的是宽度信息 *,不再是 [n]
  1089. } else {
  1090. // 尽可能解析遇到的数字
  1091. // wid:解析结果。widPresent:是否解析成功。i:待处理下标
  1092. p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end)
  1093. // [n] 必须在宽度信息之后(这就是 afterIndex 的作用)
  1094. if afterIndex && p.fmt.widPresent { // 避免 "%[3]2d"
  1095. p.goodArgNum = false
  1096. }
  1097. }
  1098.  
  1099. // 处理精度信息
  1100.  
  1101. if i+1 < end && format[i] == '.' {
  1102. i++ // 跳过小数点
  1103. // [n] 必须在精度信息之后
  1104. // 如果没有设置宽度信息,可能会出现下面的错误写法
  1105. if afterIndex { // 避免 "%[3].2d"
  1106. p.goodArgNum = false
  1107. }
  1108.  
  1109. // 处理 [n](这里处理 [n] 是为后面处理 [n]* 精度值做准备,
  1110. // 因为要从相应的 arg 中读取精度值)
  1111. argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
  1112.  
  1113. // 处理从 arg 中获取的精度信息 *
  1114. // * 表示用 args[argNum] 的值作为精度值来格式化 args[argNum+1]
  1115. if i < end && format[i] == '*' {
  1116. i++ // 跳过 * 号
  1117.  
  1118. // prec:args[argNum] 的值。precPresent:prec 是否设置成功。
  1119. // argNum:argNum+1(无论 prec 是否设置成功,只要不超出 args 数量)
  1120. p.fmt.prec, p.fmt.precPresent, argNum = intFromArg(a, argNum)
  1121.  
  1122. // 负精度值没有意义
  1123. if p.fmt.prec < 0 {
  1124. p.fmt.prec = 0
  1125. p.fmt.precPresent = false
  1126. }
  1127. // 精度值设置失败,处理无效精度(仅显示一个提示,不影响其它部分的处理)
  1128. if !p.fmt.precPresent {
  1129. p.buf.WriteString(badPrecString) // "%!(BADPREC)"
  1130. }
  1131. afterIndex = false // 刚处理的是精度信息 *,不再是 [n]。
  1132. } else {
  1133. // 尽可能解析遇到的数字
  1134. // prec:解析结果。precPresent:是否解析成功。i:待处理下标。
  1135. p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i, end)
  1136. // 如果没有指定精度值,则默认精度为 0。
  1137. if !p.fmt.precPresent {
  1138. p.fmt.prec = 0 // 这个好像不用设置,parsenum 失败则 prec 肯定为 0。
  1139. p.fmt.precPresent = true // 针对 fmt.Printf("%#8.d", 0) 的情况
  1140. // 这里可能是一个小疏忽,忽略了 "%.[3]2d" 这种错误的写法。
  1141. // 下面一行代码经过了修改,并且增加了 2 行代码。
  1142. // [n] 必须在精度值之后。
  1143. } else if afterIndex && !p.fmt.precPresent { // 拒绝 "%.[3]2d",允许 "%.[2]f"
  1144. p.goodArgNum = false
  1145. }
  1146. }
  1147. }
  1148.  
  1149. // 在宽度信息和精度信息之后可以指定新的 [n],用以指示要格式化的 arg,所以
  1150. // 这里需要再次获取 [n]。如果之前没有处理宽度和精度信息,那么 [n] 在处理
  1151. // 宽度信息之前就已经获取过了,这里就不需要再次获取。
  1152. if !afterIndex {
  1153. argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
  1154. }
  1155.  
  1156. // 如果 arg 索引之后没有了内容,则说明缺少必要的动词
  1157. if i >= end {
  1158. p.buf.WriteString(noVerbString) // "%!(NOVERB)"
  1159. break
  1160. }
  1161.  
  1162. // 获取最后的动词
  1163. verb, w := utf8.DecodeRuneInString(format[i:])
  1164. i += w // 跳过最后的动词
  1165.  
  1166. // 处理特殊动词和错误信息
  1167. switch {
  1168. case verb == '%': // %% 解析为一个 % 写入
  1169. p.buf.WriteByte('%')
  1170. case !p.goodArgNum: // argNum 无效(由于 [n] 指定错误,或者放错了位置)
  1171. p.badArgNum(verb)
  1172. case argNum >= len(a): // argNum 超出范围(一般因为 arg 数量不够)
  1173. p.missingArg(verb)
  1174. case verb == 'v': // 特殊动词 #v 和 +v
  1175. // Go 语法格式
  1176. p.fmt.sharpV = p.fmt.sharp
  1177. p.fmt.sharp = false
  1178. // 结构体字段语法格式
  1179. p.fmt.plusV = p.fmt.plus
  1180. p.fmt.plus = false
  1181. fallthrough
  1182. default:
  1183. // 开始解析 arg
  1184. p.printArg(a[argNum], verb)
  1185. // 准备处理下一个 arg
  1186. argNum++
  1187. }
  1188. }
  1189.  
  1190. // 所有占位符都处理完毕
  1191.  
  1192. // 检查多余的 arg(提供的 arg 过多)
  1193. // 如果在占位符中使用了 [n],则跳过这里的检查
  1194. if !p.reordered && argNum < len(a) {
  1195. p.fmt.clearflags() // 清空旗标,开始处理多余的 arg
  1196. p.buf.WriteString(extraString) // "%!(EXTRA "
  1197. for i, arg := range a[argNum:] {
  1198. if i > 0 { // 第一个 arg 之前不添加分隔符
  1199. p.buf.WriteString(commaSpaceString) // ", "
  1200. }
  1201. if arg == nil {
  1202. p.buf.WriteString(nilAngleString)
  1203. } else {
  1204. p.buf.WriteString(reflect.TypeOf(arg).String())
  1205. p.buf.WriteByte('=')
  1206. p.printArg(arg, 'v') // 使用 v 动词处理所有 arg
  1207. }
  1208. }
  1209. p.buf.WriteByte(')')
  1210. }
  1211. }
  1212.  
  1213. // 格式化 a 中提供的 arg,在非字符串 arg 之间添加空格
  1214. func (p *pp) doPrint(a []interface{}) {
  1215. prevString := false
  1216. for argNum, arg := range a {
  1217. isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
  1218. // 在所有非字符串 arg 之间添加空格
  1219. if argNum > 0 && !isString && !prevString {
  1220. p.buf.WriteByte(' ')
  1221. }
  1222. p.printArg(arg, 'v') // 使用 v 动词处理所有 arg
  1223. prevString = isString
  1224. }
  1225. }
  1226.  
  1227. // 格式化 a 中提供的 arg,在所有 arg 之间添加空格,并在最后添加换行符
  1228. func (p *pp) doPrintln(a []interface{}) {
  1229. for argNum, arg := range a {
  1230. // 在所有 arg 之间添加空格
  1231. if argNum > 0 {
  1232. p.buf.WriteByte(' ')
  1233. }
  1234. p.printArg(arg, 'v') // 使用 v 动词处理所有 arg
  1235. }
  1236. p.buf.WriteByte('\n') // 尾部添加换行符
  1237. }

  

Go语言fmt库的print函数源码解析的更多相关文章

  1. Vue中之nextTick函数源码分析

    Vue中之nextTick函数源码分析 1. 什么是Vue.nextTick()?官方文档解释如下:在下次DOM更新循环结束之后执行的延迟回调.在修改数据之后立即使用这个方法,获取更新后的DOM. 2 ...

  2. PHP 源码 — intval 函数源码分析

    PHP 源码 - intval 函数源码分析 文章来源: https://github.com/suhanyujie/learn-computer/ 作者:suhanyujie 基于PHP 7.3.3 ...

  3. PHP 源码 —— is_array 函数源码分析

    is_array 函数源码分析 本文首发于 https://github.com/suhanyujie/learn-computer/blob/master/src/function/array/is ...

  4. [转]delphi 有授权许可的字符串拷贝函数源码

    一段看上去“貌不惊人”的Delphi插入汇编代码,却需要授权许可,但是与经典的同类型函数比较,确实“身手不凡”. 研究代码的目的在于借鉴,本文通过分析,并用C++重写代码进行比较,再次证明这段代码效率 ...

  5. mongodb操作:利用javaScript封装db.collection.find()后可调用函数源码解读

    { "_mongo" : connection to YOURIP:27017{ SSL: { sslSupport: false, sslPEMKeyFile: "&q ...

  6. lodash框架中的chunk与drop函数源码逐行分析

    lodash是一个工具库,跟underscore差不多 chunk函数的作用: 把一维数组,按照固定的长度分段成二维数组 如: chunk( [ 10, 20, 30, 40 ], 2 )     结 ...

  7. python 内置函数源码查看

    如果是用python 实现的模块可以直接在IDE里面追踪到源码 也可以使用help内置函数,例如: help(os) 如果是c 语言实现的模块,则不能直接在IDE里面查看,如果直接在IDE里面查看,会 ...

  8. 巡风视图函数源码学习--view.py

    记录一下巡风扫描器view.py这个脚本里的视图函数的学习,直接在代码里面做的注释,里面有一些print 代码是为了把数据打印出来小白我自己加的,勿怪勿怪.可能存在一些理解错误和不到位的地方,希望大佬 ...

  9. Spark GraphX的函数源码分析及应用实例

    1. outerJoinVertices函数 首先给出源代码 override def outerJoinVertices[U: ClassTag, VD2: ClassTag] (other: RD ...

随机推荐

  1. JavaScript本地存储实践(html5的localStorage和ie的userData)

    http://www.css88.com/archives/3717 JavaScript本地存储实践(html5的localStorage和ie的userData) 发表于 2011年06月11日  ...

  2. Jackson 使用

    // 序列化出来的 JSON, 不包含值为 NULL 类型字段. mapper.setSerializationInclusion(Include.NON_NULL); Jackson provide ...

  3. 【刷题】BZOJ 3531 [Sdoi2014]旅行

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...

  4. Web前端开发神器--WebStorm(JavaScript 开发工具) 8.0.3 中文汉化破解版

    WebStorm(JavaScript 开发工具) 8.0.3 中文汉化破解版 http://www.jb51.net/softs/171905.html WebStorm 是jetbrains公司旗 ...

  5. BZOJ2802 [Poi2012]Warehouse Store 【贪心】

    题目链接 BZOJ2802 题解 这样的问题通常逆序贪心 每个\(A[i]\)只能用来满足后面的\(B[i]\) 就用当前\(A[i]\)不断提供给最小的\(B[i]\)即可 用一个堆维护 #incl ...

  6. keepalived回顾

    Keepalived是lvs的扩展项目,因此它们之间具备良好的兼容性. 通过对服务器池对象的健康检查,实现对失效机器/服务的故障隔离: 负载均衡器之间的失败切换failover,通过VRRPv2 st ...

  7. 搭建ELK收集Nginx日志

    众所周知,ELK是日志收集套装,这里就不多做介绍了. 画了一个粗略的架构图,如下: 这里实际用了三个节点,系统版本为CentOS6.6,ES版本为2.3.5,logstash版本为2.4.0,kiba ...

  8. 解题:SCOI 2005 骑士精神

    题面 我把这个当做IDA*的模板题的说,说说我个人对IDA*的理解 IDA*是一个DFS,和A*一样,它也有一个乐观的估价函数.这里这个估价函数是用来限制状态的扩展的,如果当前代价加上乐观的估计都无法 ...

  9. Jenkins(一)---我理解的jenkins是这样的

    1.齿轮 如果将 java / maven / ant / git / tomcat / jenkins 等等软件比喻为齿轮:如下图 两个软件在一起可以驱动另外一个软件:如下图 如果把这些软件要集成在 ...

  10. MySQL基本了解与使用

    MySQL的相关概念介绍 MySQL 为关系型数据库(Relational Database Management System), 这种所谓的"关系型"可以理解为"表格 ...