为什么读取后的io.reader在golang中变为空?

joy*_*joy 2 io go

func foo(buf *bytes.Buffer) {
    fmt.Println("0: ", len(buf.Bytes()))
    ioutil.ReadAll(buf)
    fmt.Println("1: ", len(buf.Bytes()))
}
Run Code Online (Sandbox Code Playgroud)

首次运行代码将打印正确的长度,但第二次打印长度为零.

icz*_*cza 8

bytes.Buffer漏极读取或消耗读取的字节.这意味着如果您再次尝试阅读,则不会返回.

Buffer.Bytes()返回缓冲区的未读部分,因此0在读完所有内容后,您可以看到预期的结果(这正是ioutil.ReadAll()这样).


如果你只想"偷看"而不是真正"读"字节怎么办?

没有"偷看"功能bytes.Buffer.最简单的方法是获取缓冲区的字节,然后bytes.Buffer从中构造另一个缓冲区并从新缓冲区中读取.

它可能看起来像这样:

func peek(buf *bytes.Buffer, b []byte) (int, error) {
    buf2 := bytes.NewBuffer(buf.Bytes())
    return buf2.Read(b)
}
Run Code Online (Sandbox Code Playgroud)

peek() 在行动:

为简单起见省略了错误检查

buf := &bytes.Buffer{}

buf.WriteString("Hello")
fmt.Printf("Len: %d, Content: %s\n", buf.Len(), buf)

fmt.Println("\nPeeking...")
data := make([]byte, 4)
peek(buf, data)
fmt.Printf("Peeked: %s\n", data)
fmt.Printf("Len: %d, Content: %s\n", buf.Len(), buf)

fmt.Println("\nReading...")
data = make([]byte, buf.Len())
buf.Read(data)
fmt.Printf("Read: %s\n", data)
fmt.Printf("Len: %d, Content: %s\n", buf.Len(), buf)
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

Len: 5, Content: Hello

Peeking...
Peeked: Hell
Len: 5, Content: Hello

Reading...
Read: Hello
Len: 0, Content: 
Run Code Online (Sandbox Code Playgroud)