在Go语言中,打印`bytes.Buffer`时会出现不同的行为

4
当我执行这个命令时:
buf := new(bytes.Buffer)
buf.WriteString("Hello world")
fmt.Println(buf)

这段代码会输出 Hello World

但如果我执行以下代码:

var buf bytes.Buffer
buf.WriteString("Hello world")
fmt.Println(buf)

它打印出来的是:{[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}

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


它目前打印了Buffer切片中给定ASCII字符的十进制表示。请参阅bytes.BufferString()方法。 - Berkant İpek
1
new(bytes.Buffer) 返回的是 *bytes.Buffer,而不是 bytes.Buffer。因此,这两个 buf 是不同的 :) - starriet
1个回答

18
因为类型为*bytes.Buffer的值具有String()方法(*bytes.Buffer方法集包含String()方法),而类型为bytes.Buffer的值则没有。
并且fmt包检查被打印的值是否具有String() string方法,如果是,则调用该方法生成该值的字符串表示形式。
引用自fmt包文档:
除使用%T和%p动词打印时,对于实现特定接口的操作数,应用特殊格式化考虑。按应用顺序排列如下:
  1. 如果操作数是reflect.Value,则该操作数将被其持有的具体值替换,并继续使用下一条规则进行打印。
  2. 如果操作数实现了Formatter接口,则将调用该操作数。Formatter提供了精细的格式控制。
  3. 如果使用#标志(%#v)使用%v动词,并且操作数实现了GoStringer接口,则将调用该接口。

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

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

Buffer.String()方法将其内容作为字符串返回,这是在传递类型为*bytes.Buffer的指针时打印的内容。当您传递类型为bytes.Buffer的非指针值时,它只是像普通结构值一样打印,其默认格式为:

{field0 field1 ...}

相关/类似问题:

t和*t之间的区别

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接