如何从包含json数组的流中一次读取一个json对象,而不将整个数组加载到内存中?

如何从包含json数组的流中一次读取一个json对象,而不将整个数组加载到内存中?,json,go,stream,Json,Go,Stream,为了减少内存使用和延迟,我希望在http响应中返回的json对象全部发送之前开始处理它们。 我正在尝试在我的web服务客户端上编写一个方法,该方法将查询一个web服务,返回一个通道,该通道将从web请求中提供结构,作为流的结束 func (c *Client) GetMyObj() (<-chan models.MyObj, <-chan error) { outChan := make(chan models.MyObj) errChan :=

为了减少内存使用和延迟,我希望在http响应中返回的json对象全部发送之前开始处理它们。 我正在尝试在我的web服务客户端上编写一个方法,该方法将查询一个web服务,返回一个通道,该通道将从web请求中提供结构,作为流的结束

    func (c *Client) GetMyObj() (<-chan models.MyObj, <-chan error) {
       outChan := make(chan models.MyObj)
       errChan := make(chan error)
       go func() {
          resp, err := httpClient.Get(c.ServiceUrl, "text/plain;charset=UTF-8", nil)
          if err != nil {
            errChan <- err
            return
          }
          if resp.Status != "200 OK" {
             errChan <- fmt.Errorf("http error: %1", resp.Status)
             return
          }

          dec := json.NewDecoder(resp.Body)

          for dec.More() {
             myO:= models.MyObj{}
             err := dec.Decode(&MyO)
             if err != nil {
                errChan <- err
                return
             }
             outChan <- dfe
          }           
       }()

       return outChan, errChan
    }
中列出的示例正好说明了这一点

简而言之,您可以执行以下步骤:

  • 使用
    dec.token()
    读取令牌(并且可以选择将其预期为开放方括号)
  • 使用
    dec.Decode()
    读取令牌,而
    dec.More()
  • (可选)读取最后的结束方括号
  • 例如():


    (提示:
    dec.Token
    )我投票关闭这个问题,因为上面评论中链接的go文档提供了与此完全相同的示例代码。我查看了Token(),它看起来像是一直从流中读取,直到找到它读取的第一个括号或括号为止,并将所有读取部分添加到缓冲区中,如果是这种情况,它会将所有响应读取到内存中,这正是我试图避免的。我将深入研究解码器,看看我是否误解了。看起来它使用了一个缓冲窗口,而不是加载整个窗口,尽管从我的实验中我无法判断窗口大小是否每个周期增加512字节,即使是这样,这意味着它在解析1GB json文件时只会增加到略超过1MB。如果im服务多个请求,可能会出现问题,我喜欢将我的Go服务保持在spring boot应用程序配置文件的大小以下;)
        [{"name":"Value"}
        ,{"name":"Value"}
        ,{"name":"Value"}]
    
    dec := json.NewDecoder(jsonStream)
    type Item struct{ Name string }
    
    // Read the open bracket.
    t, err := dec.Token()
    if err != nil {
        panic(err)
    }
    fmt.Printf("OK: %T: %v\n", t, t)
    
    // While the array contains values.
    for dec.More() {
        // Decode an array value.
        var item Item
        err := dec.Decode(&item)
        if err != nil {
            panic(err)
        }
        fmt.Printf("OK: item=%#v\n", item)
    }
    
    // Read the closing bracket.
    t, err = dec.Token()
    if err != nil {
        panic(err)
    }
    fmt.Printf("OK: %T: %v\n", t, t)
    // OK: json.Delim: [
    // OK: item=main.Item{Name:"Value1"}
    // OK: item=main.Item{Name:"Value2"}
    // OK: item=main.Item{Name:"Value3"}
    // OK: json.Delim: ]