打印字节时的不同行为.Go中的缓冲区 [英] Different behavior when printing a bytes.Buffer in Go

查看:43
本文介绍了打印字节时的不同行为.Go中的缓冲区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我执行此操作时:

  buf:= new(bytes.Buffer)buf.WriteString("Hello world")fmt.Println(buf) 

它会打印 Hello World .

但是,如果我执行此操作:

  var buf bytes.Bufferbuf.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 00 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

我了解这是结构字节.Buffer ,但为什么以其他格式打印?

解决方案

因为类型为 * bytes.Buffer 的值具有 String()方法( * bytes.Buffer 的href ="https://golang.org/ref/spec#Method_sets" rel ="noreferrer">方法集包含 String()方法),而类型为 bytes.Buffer 的值则不会.

然后 fmt 包检查要打印的值是否具有 String()string 方法,如果是,则调用该方法以生成值的字符串表示形式

fmt 的软件包文档中的报价:

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

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

  2. 如果操作数实现Formatter接口,则将调用它.格式化程序可以很好地控制格式化.

  3. 如果%v动词与#标志(%#v)一起使用,并且操作数实现GoStringer接口,则会被调用.

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

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

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

Buffer.String()方法以 string 的形式返回其内容,这就是您传递 * bytes类型的指针时看到的内容..并且当您传递类型为 bytes.Buffer 的非指针值时,它就像普通的struct值一样被简单地打印,其默认格式为:

  {field0 field1 ...} 

查看相关/类似问题:

t和* t之间的区别

为什么不使用%v进行打印整数和字符串

为什么Error()的优先级高于String()

When I execute this:

buf := new(bytes.Buffer)
buf.WriteString("Hello world")
fmt.Println(buf)

it prints Hello World.

But if I execute this:

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

it prints: {[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}

I understand that this is the content of the structure byte.Buffer but why it is printed in a different format?

解决方案

Because a value of type *bytes.Buffer has a String() method (the method set of *bytes.Buffer contains the String() method), and a value of type bytes.Buffer does not.

And the fmt package checks if the value being printed has a String() string method, and if so, it is called to produce the string representation of the value.

Quoting from package doc of fmt:

Except when printed using the verbs %T and %p, special formatting considerations apply for operands that implement certain interfaces. In order of application:

  1. If the operand is a reflect.Value, the operand is replaced by the concrete value that it holds, and printing continues with the next rule.

  2. If an operand implements the Formatter interface, it will be invoked. Formatter provides fine control of formatting.

  3. If the %v verb is used with the # flag (%#v) and the operand implements the GoStringer interface, that will be invoked.

If the format (which is implicitly %v for Println etc.) is valid for a string (%s %q %v %x %X), the following two rules apply:

  1. If an operand implements the error interface, the Error method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).

  2. If an operand implements method String() string, that method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).

The Buffer.String() method returns its content as a string, that's what you see printed when you pass a pointer of type *bytes.Buffer. And when you pass a non-pointer value of type bytes.Buffer, it is simply printed like a normal struct value, for which the default format is:

{field0 field1 ...}

See related / similar questions:

The difference between t and *t

Why not use %v to print int and string

Why does Error() have priority over String()

这篇关于打印字节时的不同行为.Go中的缓冲区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆