XML Golang 中的编码器不会关闭所有流中的标签
XML Encoder in Golang does not close tags in all streams
我正在开发流式 XML 编码器,它将同时将 XML 写入本地文件和 S3 存储桶。但是,仅通过测试它写入两个本地文件,我可以看到其中一个文件每次都缺少结束标记。
下面是我大致的做法(省略错误处理):
func copyToFile (fileName string) {
f, _ := os.Create(fileName)
defer f.Close()
io.Copy(f, pr)
}
func main () {
pr, pw := io.Pipe()
defer pw.Close()
encoder := xml.NewEncoder(pw)
go copyToFile("file1.xml")
go copyToFile("file2.xml")
encoder.EncodeToken(xml.StartElement{...})
encoder.Encode(SomeStruct{})
encoder.EncodeToken(xml.EndElement{...})
encoder.Flush()
}
file1.xml
中的结果符合预期,所有标签都正确关闭,但在file2.xml
中缺少结束标签(encoder.EncodeToken(xml.EndElement{...})
的调用)。
我做错了什么?当我将 reader 复制到 S3 时,我能得到相同的结果吗?
返回的 io.PipeReader
不能有多个 reader,所有 reader 的数据都不会重复。 io.PipeReader
只能 "serve" 一个 reader,你启动 2 个 goroutines 来读取它。
要实现您想要的效果,请使用 io.MultiWriter()
. It returns you a single io.Writer
到您可以写入的位置,它会将写入复制到您传递给它的所有写入器。
例如:
f1 := &bytes.Buffer{}
f2 := &bytes.Buffer{}
w := io.MultiWriter(f1, f2)
encoder := xml.NewEncoder(w)
encoder.EncodeToken(xml.StartElement{Name: xml.Name{Local: "test"}})
encoder.Encode(image.Point{1, 2})
encoder.EncodeToken(xml.EndElement{Name: xml.Name{Local: "test"}})
encoder.Flush()
fmt.Println(f1)
fmt.Println(f2)
这将输出(在 Go Playground 上尝试):
<test><Point><X>1</X><Y>2</Y></Point></test>
<test><Point><X>1</X><Y>2</Y></Point></test>
以上示例写入 2 个内存缓冲区。要写入 2 个文件,您可以将 2 os.File
s 传递给 io.MultiWriter()
(或任何其他实现 io.Writer
的方法):
f1, err := os.Create("file1.xml")
if err != nil {
panic(err)
}
defer f1.Close()
f2, err := os.Create("file2.xml")
if err != nil {
panic(err)
}
defer f2.Close()
w := io.MultiWriter(f1, f2)
// ...
我正在开发流式 XML 编码器,它将同时将 XML 写入本地文件和 S3 存储桶。但是,仅通过测试它写入两个本地文件,我可以看到其中一个文件每次都缺少结束标记。
下面是我大致的做法(省略错误处理):
func copyToFile (fileName string) {
f, _ := os.Create(fileName)
defer f.Close()
io.Copy(f, pr)
}
func main () {
pr, pw := io.Pipe()
defer pw.Close()
encoder := xml.NewEncoder(pw)
go copyToFile("file1.xml")
go copyToFile("file2.xml")
encoder.EncodeToken(xml.StartElement{...})
encoder.Encode(SomeStruct{})
encoder.EncodeToken(xml.EndElement{...})
encoder.Flush()
}
file1.xml
中的结果符合预期,所有标签都正确关闭,但在file2.xml
中缺少结束标签(encoder.EncodeToken(xml.EndElement{...})
的调用)。
我做错了什么?当我将 reader 复制到 S3 时,我能得到相同的结果吗?
返回的 io.PipeReader
不能有多个 reader,所有 reader 的数据都不会重复。 io.PipeReader
只能 "serve" 一个 reader,你启动 2 个 goroutines 来读取它。
要实现您想要的效果,请使用 io.MultiWriter()
. It returns you a single io.Writer
到您可以写入的位置,它会将写入复制到您传递给它的所有写入器。
例如:
f1 := &bytes.Buffer{}
f2 := &bytes.Buffer{}
w := io.MultiWriter(f1, f2)
encoder := xml.NewEncoder(w)
encoder.EncodeToken(xml.StartElement{Name: xml.Name{Local: "test"}})
encoder.Encode(image.Point{1, 2})
encoder.EncodeToken(xml.EndElement{Name: xml.Name{Local: "test"}})
encoder.Flush()
fmt.Println(f1)
fmt.Println(f2)
这将输出(在 Go Playground 上尝试):
<test><Point><X>1</X><Y>2</Y></Point></test>
<test><Point><X>1</X><Y>2</Y></Point></test>
以上示例写入 2 个内存缓冲区。要写入 2 个文件,您可以将 2 os.File
s 传递给 io.MultiWriter()
(或任何其他实现 io.Writer
的方法):
f1, err := os.Create("file1.xml")
if err != nil {
panic(err)
}
defer f1.Close()
f2, err := os.Create("file2.xml")
if err != nil {
panic(err)
}
defer f2.Close()
w := io.MultiWriter(f1, f2)
// ...