在Go中打印bytes.Buffer时的不同行为

hor*_*rex 0 string struct pointers go

当我执行这个:

buf := new(bytes.Buffer)
buf.WriteString("Hello world")
fmt.Println(buf)
Run Code Online (Sandbox Code Playgroud)

它打印Hello World.

但是如果我执行这个:

var buf bytes.Buffer
buf.WriteString("Hello world")
fmt.Println(buf)
Run Code Online (Sandbox Code Playgroud)

它打印: {[72 101 108 108 111 32 119 111 114 108 100] 0 [72 101 108 108 111 32 119 111 114 108 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 0}

我知道这是结构byte.Buffer的内容,但为什么它以不同的格式打印?

icz*_*cza 9

因为类型的值*bytes.Buffer具有String()方法(方法集*bytes.Buffer含有String()方法),和类型的值bytes.Buffer没有.

并且fmt包检查正在打印的值是否具有String() string方法,如果是,则调用它以生成值的字符串表示.

引用包文档fmt:

除非使用动词%T和%p打印,否则特殊格式注意事项适用于实现某些接口的操作数.按申请顺序:

  1. 如果操作数是一个reflect.Value,则操作数将替换为它保存的具体值,并继续打印下一个规则.

  2. 如果操作数实现Formatter接口,则将调用它.Formatter提供格式化的精细控制.

  3. 如果%v动词与#flag(%#v)一起使用,并且操作数实现了GoStringer接口,则将调用该接口.

如果格式(对于Println等隐式%v)对字符串有效(%s%q%v%x%X),则适用以下两个规则:

  1. 如果操作数实现了错误接口,则将调用Error方法将对象转换为字符串,然后根据动词的需要对其进行格式化(如果有).

  2. 如果操作数实现方法String()字符串,则将调用该方法将对象转换为字符串,然后根据动词(如果有)格式化该字符串.

Buffer.String()方法将其内容作为a返回string,这是您在传递类型指针时看到的内容*bytes.Buffer.当你传递一个非指针类型的值时bytes.Buffer,它就像普通的struct值一样打印,默认格式为:

{field0 field1 ...}
Run Code Online (Sandbox Code Playgroud)

查看相关/类似问题:

t和*t之间的差异

为什么不使用%v来打印int和string

为什么Error()优先于String()