Golang进阶

[Go] fmt.Printf("%s", err) 怎么可能?

2022-08-02  本文已影响0人  qishuai

工作中我们会发现代码中会使用%s格式化err的情况,包括一些开源代码。但是你翻一下源码,内置的error接口里面,并没有String() string方法呀,怎么可能正常地打印error信息呢。
下面是一段代码示例:

err := errors.New("error test")
fmt.Printf("%s\n", err)
log.Printf("%s\n", err)

// output:
// error test
// 2022/08/02 11:00:30 error test

是不是觉得很奇怪,对自己的Go实践能力产生了怀疑,哈哈哈。。。不要怀疑(me too),你是Ok的,只是go的格式化输出做了特殊处理而已。
调用链路是这样的:
fmt.Printf -> fmt.Fprintf -> *pp.doPrintf -> *pp.printArg -> *pp.handleMethods

switch verb {
        case 'v', 's', 'x', 'X', 'q':
            // Is it an error or Stringer?
            // The duplication in the bodies is necessary:
            // setting handled and deferring catchPanic
            // must happen before calling the method.
            switch v := p.arg.(type) {
            case error:   // 重点在这里,对error类型的参数做了特殊处理
                handled = true
                defer p.catchPanic(p.arg, verb, "Error")
                p.fmtString(v.Error(), verb) // 调用的error.Error方法,输出里面的字符串
                return

            case Stringer:
                handled = true
                defer p.catchPanic(p.arg, verb, "String")
                p.fmtString(v.String(), verb)
                return
            }
        }

看到这里你应该明白了把。但是需要说明一下,如果有些log库自己实现了格式化逻辑,那么你就要具体情况具体分析了。

上一篇 下一篇

猜你喜欢

热点阅读