Documentation
¶
Overview ¶
Package iox contains small, context-aware extensions for the io package.
Index ¶
- Variables
- func CopyContext(ctx context.Context, lwc *LockedWriteCloser, rc io.ReadCloser) (int, error)
- func LimitReadCloser(rc io.ReadCloser, n int64) io.ReadCloser
- func NopWriteCloser(w io.Writer) io.WriteCloser
- func ReadAllContext(ctx context.Context, rc io.ReadCloser) ([]byte, error)
- type LockedWriteCloser
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrClosed = errors.New("locked writer is closed")
ErrClosed is returned when writing on a closed *LockedWriteCloser.
Functions ¶
func CopyContext ¶
func CopyContext(ctx context.Context, lwc *LockedWriteCloser, rc io.ReadCloser) (int, error)
CopyContext is a context-interruptible variant of io.Copy.
It copies from rc into lwc in a background goroutine. On return, it always closes lwc. It only closes rc when the context is canceled, to unblock any in-flight Read in the background goroutine.
On success, rc is NOT closed. The caller MUST ensure rc is closed after CopyContext returns (e.g., via defer).
The returned error is either caused by I/O or by the context.
Example ¶
ExampleCopyContext shows how to copy an HTTP response body into a buffer using iox.
Note: the caller is responsible for closing resp.Body after iox.CopyContext returns. CopyContext only closes the reader when the context is canceled.
package main
import (
"bytes"
"context"
"fmt"
"log"
"net/http"
"net/http/httptest"
"github.com/bassosimone/iox"
)
func main() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprint(w, "hello from httptest\n")
}))
defer server.Close()
resp, err := http.Get(server.URL)
if err != nil {
log.Println("request error:", err)
return
}
defer resp.Body.Close()
buff := &bytes.Buffer{}
writer := iox.NewLockedWriteCloser(iox.NopWriteCloser(buff))
if _, err := iox.CopyContext(context.Background(), writer, resp.Body); err != nil {
log.Println("copy error:", err)
return
}
fmt.Println(buff.String())
}
Output: hello from httptest
func LimitReadCloser ¶
func LimitReadCloser(rc io.ReadCloser, n int64) io.ReadCloser
LimitReadCloser wraps rc such that reads are limited to n bytes while Close forwards to the underlying rc.
func NopWriteCloser ¶
func NopWriteCloser(w io.Writer) io.WriteCloser
NopWriteCloser wraps an io.Writer and returns a no-op io.WriteCloser.
This is useful when CopyContext needs to stream into a writer that does not require closing, such as a *bytes.Buffer.
func ReadAllContext ¶
ReadAllContext is a context-interruptible variant of io.ReadAll.
It reads from rc into an internal buffer using CopyContext. On success, rc is NOT closed (the caller MUST close it, e.g., via defer). On context cancellation, rc is closed to unblock any in-flight Read.
The returned byte slice contains whatever was read before the error (if any), so partial results are available even when the context is canceled.
Types ¶
type LockedWriteCloser ¶
type LockedWriteCloser struct {
// contains filtered or unexported fields
}
LockedWriteCloser is a concurrency safe io.WriteCloser wrapper.
It serializes writes, makes Close idempotent, and keeps track of the number of bytes successfully written.
All methods are safe for concurrent use.
Close is serialized with Write, so it may block until an in-flight Write returns.
Construct using NewLockedWriteCloser.
func NewLockedWriteCloser ¶
func NewLockedWriteCloser(w io.WriteCloser) *LockedWriteCloser
NewLockedWriteCloser wraps an io.WriteCloser and returns a concurrency-safe wrapper.
func (*LockedWriteCloser) Close ¶
func (w *LockedWriteCloser) Close() error
Close ensures that subsequent writes would fail with ErrClosed.
Returns nil, ErrClosed, or the error occurred when closing the io.WriteCloser.
func (*LockedWriteCloser) Count ¶
func (w *LockedWriteCloser) Count() int
Count returns the number of bytes successfully written so far.
func (*LockedWriteCloser) LockedWrite ¶
func (w *LockedWriteCloser) LockedWrite(data []byte) (int, error)
LockedWrite writes the given bytes to the underlying io.WriteCloser.
The returned error is nil, ErrClosed when closed, or the error ocurred when attempting to write into the underlying io.WriteCloser.