为了账号安全,请及时绑定邮箱和手机立即绑定

Golang中的XML编码器不会关闭所有流中的标签

Golang中的XML编码器不会关闭所有流中的标签

Go
泛舟湖上清波郎朗 2023-08-07 14:57:40
我正在开发一个流式 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{...}))丢失。我究竟做错了什么?当我将阅读器复制到 S3 时,我能得到相同的结果吗?
查看完整描述

1 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

返回的数据上不能有多个读取器io.PipeReader,数据不会为所有读取器重复。只能io.PipeReader“服务”一个读者,并且您启动 2 个 goroutine 来从中读取。

要实现您想要的效果,请使用io.MultiWriter(). 它会向您返回一个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(或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)


// ...


查看完整回答
反对 回复 2023-08-07
  • 1 回答
  • 0 关注
  • 87 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信