在Go的读者中包装作家?

时间:2015-04-18 01:31:50

标签: go

我试图在Go中编写一个函数来生成XML并为它返回一个阅读器。但是,XML编码器似乎需要编写器才能写入,并且我不太确定如何将编写器的输出传递给我想要返回的读者。

我试过了:

func (i *Item) ToRss() io.Reader {                                                     
  reader, writer := io.Pipe()                                                             
  enc := xml.NewEncoder(writer)                                                           
  enc.Indent("  ", "   ")                                                                 
  enc.Encode(i)                                                                           
  return reader                                                                           
}

但是当我运行以下内容时,我会收到一个致命的错误:

  r := a.ToRss()
  buf := new(bytes.Buffer)
  buf.ReadFrom(r)
  s := buf.String()
  fmt.Println(s)

致命错误:所有goroutine都睡着了 - 死锁!

最后,我想将读者管道输出到HTTP请求的输出。我应该只返回一个[]字节吗?或者有一种缓冲输出的好方法,以便客户端可以使用阅读器吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

管道没有内部缓冲。它会在读或写时阻塞,直到调用相应的写或读。

您应该在ToRss中使用bytes.Buffer并将其作为读者返回:

func ToRss() io.Reader {
    buf := &bytes.Buffer{}
    io.WriteString(buf, "foo")
    return buf
} 

Playground link

或者,您可以启动一个新的goroutine来写入管道并将其返回以从主goroutine上读取。这种方法可以避免不必要的缓冲,但会引入另一种goroutine。

func ToRss() io.Reader {
   reader, writer := io.Pipe()
   go func() {
      io.WriteString(writer, "foo")
      writer.Close()
   }()
   return reader
}

Playground Link