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

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

我已经阅读了几个库的源代码,从我所看到的,我基本上有两种编码和解码JSONstring的可能性。

使用json.Unmarshal传递整个响应string

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

或者使用json.NewDecoder.Decode

 err = json.NewDecoder(resp.Body).Decode(value) 

在我的情况下,当处理实现io.Reader HTTP响应时,第二个版本似乎需要更less的代码,但是因为我已经看到了两者,我想知道是否应该使用解决scheme,而不是使用其他解决scheme。

而且, 从这个问题接受的答案说

请使用json.Decoder代替json.Unmarshal

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

这真的取决于你的input是什么。 如果您查看json.DecoderDecode方法的json.Decoder ,它会将整个JSON值caching到内存中,然后将其解组为一个Go值。 所以在大多数情况下,它不会有更高的内存效率(尽pipe在未来的语言版本中这很容易改变)。

所以一个更好的经验法则是:

  • 如果数据来自io.Readerstream,则使用json.Decoder ,或者需要解码来自数据stream的多个值。
  • 如果您已经在内存中有JSON数据,请使用json.Unmarshal

对于从HTTP请求读取的情况,我会selectjson.Decoder因为您显然正在读取stream。

我们必须在解码之前从pipe道获取[]字节,所以在处理HTTP连接时需要从io读取,所以我认为这两个函数是相等的。 但是当数据保存在内存中,或者我们已经得到了[]字节的时候,我们可以直接使用Unmarshal ,这样比较好。

在读取和写入HTTP连接,WebSockets或文件时使用json.Decoder

当input是[]字节时使用json.Unmarshal