|  | // Copyright 2010 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package io | 
|  |  | 
|  | type multiReader struct { | 
|  | readers []Reader | 
|  | } | 
|  |  | 
|  | func (mr *multiReader) Read(p []byte) (n int, err error) { | 
|  | for len(mr.readers) > 0 { | 
|  | n, err = mr.readers[0].Read(p) | 
|  | if n > 0 || err != EOF { | 
|  | if err == EOF { | 
|  | // Don't return EOF yet. There may be more bytes | 
|  | // in the remaining readers. | 
|  | err = nil | 
|  | } | 
|  | return | 
|  | } | 
|  | mr.readers = mr.readers[1:] | 
|  | } | 
|  | return 0, EOF | 
|  | } | 
|  |  | 
|  | // MultiReader returns a Reader that's the logical concatenation of | 
|  | // the provided input readers.  They're read sequentially.  Once all | 
|  | // inputs have returned EOF, Read will return EOF.  If any of the readers | 
|  | // return a non-nil, non-EOF error, Read will return that error. | 
|  | func MultiReader(readers ...Reader) Reader { | 
|  | r := make([]Reader, len(readers)) | 
|  | copy(r, readers) | 
|  | return &multiReader{r} | 
|  | } | 
|  |  | 
|  | type multiWriter struct { | 
|  | writers []Writer | 
|  | } | 
|  |  | 
|  | func (t *multiWriter) Write(p []byte) (n int, err error) { | 
|  | for _, w := range t.writers { | 
|  | n, err = w.Write(p) | 
|  | if err != nil { | 
|  | return | 
|  | } | 
|  | if n != len(p) { | 
|  | err = ErrShortWrite | 
|  | return | 
|  | } | 
|  | } | 
|  | return len(p), nil | 
|  | } | 
|  |  | 
|  | var _ stringWriter = (*multiWriter)(nil) | 
|  |  | 
|  | func (t *multiWriter) WriteString(s string) (n int, err error) { | 
|  | var p []byte // lazily initialized if/when needed | 
|  | for _, w := range t.writers { | 
|  | if sw, ok := w.(stringWriter); ok { | 
|  | n, err = sw.WriteString(s) | 
|  | } else { | 
|  | if p == nil { | 
|  | p = []byte(s) | 
|  | } | 
|  | n, err = w.Write(p) | 
|  | } | 
|  | if err != nil { | 
|  | return | 
|  | } | 
|  | if n != len(s) { | 
|  | err = ErrShortWrite | 
|  | return | 
|  | } | 
|  | } | 
|  | return len(s), nil | 
|  | } | 
|  |  | 
|  | // MultiWriter creates a writer that duplicates its writes to all the | 
|  | // provided writers, similar to the Unix tee(1) command. | 
|  | func MultiWriter(writers ...Writer) Writer { | 
|  | w := make([]Writer, len(writers)) | 
|  | copy(w, writers) | 
|  | return &multiWriter{w} | 
|  | } |