dongpiao1983 2019-04-08 12:51
浏览 162
已采纳

如何将大量数据封送至XML

I need to send a large amount of data via XML and my Docker container runs out of memory when performing the task. Is there a way using Go to incrementally marshal a large XML document and also incrementally write it to a file so as to minimize memory usage?

  • 写回答

1条回答 默认 最新

  • dotwc62080 2019-04-08 13:18
    关注

    Use xml.Encoder to stream the XML output to an io.Writer that may be a network connection (net.Conn) or a file (os.File). The complete result will not be kept in memory.

    You may use Encoder.Encode() to encode a Go value to XML. Generally you may pass any Go value that you would pass to xml.Marshal().

    Encoder.Encode() only helps if the data you want to marshal is ready in-memory, which may or may not be feasible to you. E.g. if you want to marshal a large list which cannot (or should not) be read into memory, this will not be a salvation to you.

    If the input data also cannot be held in memory, then you may construct the XML output by tokens and elements. You may use Encoder.EncodeToken() for this which allows you to write "parts" of the result XML document.

    For example if you want to write a large list to the output, you may write a start element tag (e.g. <list>), then write the elements of the list one-by-one (each fetched from database or from file, or constructed by an algorithm on-the-fly), and once the list is marshaled, you may close the list element tag (</list>).

    Here's a simple example how you can do that:

    type Student struct {
        ID   int
        Name string
    }
    
    func main() {
        he := func(err error) {
            if err != nil {
                panic(err) // In your app, handle error properly
            }
        }
    
        // For demo purposes we use an in-memory buffer,
        // but this may be an os.File too.
        buf := &bytes.Buffer{}
    
        enc := xml.NewEncoder(buf)
        enc.Indent("", "  ")
    
        he(enc.EncodeToken(xml.StartElement{Name: xml.Name{Local: "list"}}))
        for i := 0; i < 3; i++ {
            // Here you can fetch / construct the records
            he(enc.Encode(Student{ID: i, Name: string(i + 'A')}))
        }
        he(enc.EncodeToken(xml.EndElement{Name: xml.Name{Local: "list"}}))
        he(enc.Flush())
    
        fmt.Println(buf.String())
    }
    

    Output of the above is (try it on the Go Playground):

    <list>
      <Student>
        <ID>0</ID>
        <Name>A</Name>
      </Student>
      <Student>
        <ID>1</ID>
        <Name>B</Name>
      </Student>
      <Student>
        <ID>2</ID>
        <Name>C</Name>
      </Student>
    </list>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端
  • ¥15 基于PLC的三轴机械手程序
  • ¥15 多址通信方式的抗噪声性能和系统容量对比
  • ¥15 winform的chart曲线生成时有凸起
  • ¥15 msix packaging tool打包问题
  • ¥15 finalshell节点的搭建代码和那个端口代码教程
  • ¥15 Centos / PETSc / PETGEM
  • ¥15 centos7.9 IPv6端口telnet和端口监控问题
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作