使用bytes.Buffer与使用*bytes.NewBuffer时json.Unmarshal的区别

kbi*_*nce 4 go

我在查看bytes包.如果我使用bytes.Buffer定义一个缓冲区,那么下面的代码工作,我得到一个输出.但是,如果我尝试创建具有一定容量的缓冲区,然后尝试相同的代码,则会失败,并显示错误错误:无效字符'\ x00'正在查找值的开头.不知道如何解决它.

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
)

func main() {
    var jsonBlob = []byte(`[
        {"Name": "Platypus", "Order": "Monotremata"},
            {"Name": "Quoll",    "Order": "Dasyuromorphia"}
            ]`)

    //var b bytes.Buffer
    b := *bytes.NewBuffer(make([]byte, 20))
    b.Write(jsonBlob)

    fmt.Println(b.String())

    var dat interface{}
    err := json.Unmarshal(b.Bytes(), &dat)
    if err != nil {
        fmt.Println("error:", err)
    }   
    fmt.Printf("%+v", dat)
}
Run Code Online (Sandbox Code Playgroud)

使用bytes.Buffer输出Run

[
        {"Name": "Platypus", "Order": "Monotremata"},
        {"Name": "Quoll",    "Order": "Dasyuromorphia"}
    ]
[map[Name:Platypus Order:Monotremata] map[Name:Quoll Order:Dasyuromorphia]]
Program exited.
Run Code Online (Sandbox Code Playgroud)

使用bytes.NewBuffer运行输出

[
        {"Name": "Platypus", "Order": "Monotremata"},
        {"Name": "Quoll",    "Order": "Dasyuromorphia"}
    ]
error: invalid character '\x00' looking for beginning of value
<nil>
Run Code Online (Sandbox Code Playgroud)

Cer*_*món 7

所述NewBuffer函数使用参数作为缓冲器的初始内容.该调用make([]byte, 20)返回一个包含20个零字节的字节片.之后缓冲区的内容b.Write(jsonBlob)是20个零字节,后跟JSON文本.

添加fmt.Printf("%q\n", b.String())到程序以查看缓冲区的内容.

playground example with printf added

JSON解析器抱怨第一个零字节.

如果您的目标是设置内部缓冲区的大小,请使用以下代码:

b := bytes.NewBuffer(make([]byte, 0, 20))
Run Code Online (Sandbox Code Playgroud)

该调用make([]byte, 0, 20)返回容量为20的零长度切片.

playground example with zero length slice

类型的变量byte.Buffer作为空缓冲区开始.

如果您的目标是限制读取的数据量,请使用io.LimitedReader.例如:

f, err := os.Open("filename")
if err != nil {
   // handle error
}
defer f.Close()
err := json.NewDecoder(&io.LimitedReader{N: 20, R: f}).Decode(&dat)
if err != nil {
    // handle error. Will get parse error if file is truncated. 
}
Run Code Online (Sandbox Code Playgroud)