使用json.Unmarshal vs json.NewDecoder.Decode解码Golang中的JSON

Sim*_*tti 174 json go

我正在开发一个API客户端,我需要根据请求对JSON有效负载进行编码,并从响应中解码JSON主体.

我已经阅读了几个库的源代码,从我看到的,我基本上有两种编码和解码JSON字符串的可能性.

使用json.Unmarshal传递整个响应字符串

data, err := ioutil.ReadAll(resp.Body)
if err == nil && data != nil {
    err = json.Unmarshal(data, value)
}
Run Code Online (Sandbox Code Playgroud)

或使用 json.NewDecoder.Decode

err = json.NewDecoder(resp.Body).Decode(value)
Run Code Online (Sandbox Code Playgroud)

在我的情况下,当处理实现的HTTP响应时,io.Reader第二个版本似乎需要更少的代码,但是因为我已经看到两者我想知道是否有任何偏好我是否应该使用解决方案而不是另一个.

此外,从这个问题接受的答案

请使用json.Decoder而不是json.Unmarshal.

但它没有提到原因.我真的应该避免使用json.Unmarshal吗?

Jam*_*dge 210

这实际上取决于你的输入.如果查看Decode方法的实现json.Decoder,它会将整个JSON值缓存到内存中,然后再将其解组为Go值.因此,在大多数情况下,它将不再具有更高的内存效率(尽管在未来的语言版本中这很容易改变).

所以更好的经验法则是:

  • 使用json.Decoder,如果你的数据从一个即将io.Reader流,或者需要多个值,从数据流进行解码.
  • json.Unmarshal如果您已在内存中拥有JSON数据,请使用此选项.

对于从HTTP请求中读取的情况,我会选择,json.Decoder因为您显然是从流中读取的.

  • 另外:通过检查Go 1.3源代码,我们还可以了解到,对于编码,如果使用json.Encoder,它将重用一个全局缓冲池(由新的sync.Pool支持),这应该可以减少缓冲区流失如果你编码了很多json.只有一个全局池如此不同json.Encoder共享它.无法对json.Marshal接口执行此操作的原因是因为字节返回给用户,并且用户无法将字节"返回"到池中.因此,如果您正在进行大量编码,json.Marshal总会有相当多的缓冲区流失. (22认同)

Sam*_*ape 9

我在《Go Web 编程》一书中找到了这段话。但没有给出任何解释

那么我们什么时候使用 Decoder 和 Unmarshal 呢?

这取决于输入。如果您的数据来自 io.Reader 流(例如 http.Request 的正文),请使用 Decoder。如果数据位于字符串或内存中的某个位置,请使用 Unmarshal。