在Go中用读者包裹作家吗?

I'm trying to write a function in Go which generates XML and returns a reader for it. However, the XML encoder seems to take a writer to write to and I'm not quite sure how to pipe the output of the writer to the reader I want to return.

I tried this:

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

But when I run the following I get a fatal error:

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

fatal error: all goroutines are asleep - deadlock!

Eventually I'd like to pipe the reader to the output of an HTTP request. Should I just return a []byte? Or is there a nice way to buffer the output so the client can use the reader?

Thanks!

A pipe does no internal buffering. It blocks on read or write until a corresponding write or read is called.

You should use a bytes.Buffer inside ToRss and return it as your reader:

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

Playground link

Alternatively you could start a new goroutine to write to the pipe and return it to be read from on the main goroutine. This method will avoid unnecessary buffering, but does introduce another goroutine.

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

Playground Link