Documentation ¶
Overview ¶
Package readwhilewrite provides a reader and a writer which is used to read a file while the writer is writing to the same file.
When readers get an EOF they waits further writes by the writer. The writer notify readers when it writes data.
Example ¶
package main import ( "io" "io/ioutil" "log" "os" "time" "github.com/hnakamur/readwhilewrite" ) func main() { file, err := ioutil.TempFile("", "test") if err != nil { log.Fatal(err) } defer os.Remove(file.Name()) w := readwhilewrite.NewWriter(file) done := make(chan struct{}) go func() { defer close(done) err := func() error { f, err := os.Open(file.Name()) if err != nil { return err } r := readwhilewrite.NewReader(f, w) defer r.Close() var buf [4096]byte for { n, err := r.Read(buf[:]) if err == io.EOF { break } if err != nil { return err } if n > 0 { os.Stdout.Write(buf[:n]) } } return nil }() if err != nil { log.Fatalf("Unexpected reader error=%v", err) } }() err = func() error { _, err := w.Write([]byte("hello\n")) if err != nil { return err } time.Sleep(time.Second) _, err = w.Write([]byte("world\n")) if err != nil { return err } time.Sleep(time.Second) _, err = w.Write([]byte("goodbye\n")) if err != nil { return err } time.Sleep(time.Second) _, err = w.Write([]byte("see you\n")) if err != nil { return err } return nil }() if err != nil { // You should log the error in production here. w.Abort() } w.Close() <-done }
Output: hello world goodbye see you
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var WriteAborted = errors.New("write aborted")
WriteAborted is an error which is returned to Read of readers when Abort and then Close is called for a writer.
Functions ¶
func SendFileHTTP ¶
func SendFileHTTP(ctx context.Context, w http.ResponseWriter, file *os.File, fw *Writer) (n int64, err error)
SendFileHTTP serves a file as a HTTP response while fw is writing to the same file.
Once it gets an EOF, it waits more writes by the writer. If the ctx is done while waiting, SendFileHTTP returns. Typically you want to pass r.Context() as ctx for r *http.Request.
If you set the Content-Length header before calling SendFileHTTP, the sendfile system call is used on Linux.
Types ¶
type Reader ¶
type Reader struct { io.ReadCloser // contains filtered or unexported fields }
Reader is a reader which waits writes by the writer when the reader gets an EOF. When the reader gets an EOF after Close is called for the writer, then it is treated as a real EOF.
func NewReader ¶
func NewReader(r io.ReadCloser, w *Writer) *Reader
NewReader creates a new reader which waits writes by the writer.
func (*Reader) Close ¶
Close implements the io.Closer interface.
Close closes the underlying reader.
func (*Reader) Read ¶
Read implements the io.Reader interface.
When Abort and then Close is called for the writer, WriteAborted is returned as err.
When SetWaitContext was called before calling Read and the context is done during waiting writes by the writer, the error from the context is returned as err.
func (*Reader) SetWaitContext ¶
SetWaitContext sets the context for waiting writes by the writer after the reader received a temporary EOF in Read.
Note SetWaitContext does not set a deadline for Read of the underlying reader. If you want to set a deadline, you need to call an appropriate method for the underlying reader yourself, for example SetReadDeadline of *os.File.
Also note SetReadDeadline of *os.File is not supported for ordinal files on most systems. See document of SetDeadline of *os.File.
type Writer ¶
type Writer struct { io.WriteCloser // contains filtered or unexported fields }
Writer is a writer which notifies readers of writes.
func (*Writer) Abort ¶
func (w *Writer) Abort()
Abort is used to make readers stop reading when some error happens in the Writer. You must call Close after Abort.