如何将大量数据封送至XML

Fis*_*ger 1 xml marshalling go

我需要通过XML发送大量数据,并且执行任务时Docker容器内存不足。有没有一种方法可以使用Go逐步封送一个大型XML文档并将其逐步写入一个文件,以最大程度地减少内存使用量?

icz*_*cza 6

用于xml.Encoder将XML输出流式传输到,io.Writer它可以是网络连接(net.Conn)或文件(os.File)。完整的结果将不会保存在内存中。

您可以用来Encoder.Encode()将Go值编码为XML。通常,您可以传递将传递给的任何Go值xml.Marshal()

Encoder.Encode()仅在您要封送的数据已在内存中准备好(可能对您可行或不可行)时才有帮助。例如,如果您想封送一个无法(或不应)读入内存的大列表,这对您来说不是一个拯救。

如果输入数据也不能保存在内存中,则可以通过标记和元素构造XML输出。您可以使用Encoder.EncodeToken()它来编写结果XML文档的“部分”。

例如,如果您想在输出中写入一个大列表,则可以编写一个开始元素标签(例如<list>),然后一一写入列表中的元素(每个元素都从数据库或文件中提取,或者由算法),然后将列表整理后,您可以关闭列表元素标签(</list>)。

这是一个简单的示例,您如何执行此操作:

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())
}
Run Code Online (Sandbox Code Playgroud)

上面的输出是(在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>
Run Code Online (Sandbox Code Playgroud)