Fmt 输出包
留个坑----
关于这个包,其实有不少很不错的实现
比如: fmt.Output()
pool
存储暂时的对象,这些对象很可能会被存储以及调用
使用sync/pool,创建了一个动态长度的buffer,可以根据需求扩展以及收缩, 但是不适用于短时间生存的
Sprintf
直接看一道题
type yoyo struct{
Name string
}
func (y *yoyo) do() string{
return fmt.Sprintf("%+v",y)
}
func main(){
p:=&yoyo{}
p.do()
}
答案是输出stack overflow
二话不说直接dlv进去看: 贴图先不给, 大概流程是,fmt.sprintf里面会调用 doPrintf(format,a) 这个函数就是loop format里面的字符串(即我们传入的 “%+v”) 遇到% , +v这种特殊字符就停止 调用
printArgs(arg ,verb rune)
这个函数会进行一个简单的判断,arg的类型,有些类型如果用cast (T.(type)这种模式)可以转换,则不需要使用反射, 如果要用反射, 即上面题目中,传入的指针y; 进入 handleMethods(verb rune)
- 判断是不是formatter?
- 判断这个verb的类型(v,s,x,X,q)中的一种,如果是,会继续判断传入的p.arg.(type) 是否是error还是一个Stringer
进入p.fmtString(v.String(),verb),其中v=p.arg.(type)实际就是最一开始传入的参数 y
这时候就会发现,这个v.String()就又回到最初的yoyo.String()方法,就会造成死循环,栈溢出;
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!