Skip to content

Instantly share code, notes, and snippets.

@dillonstreator
Last active August 21, 2023 00:36
Show Gist options
  • Save dillonstreator/3e9162e6e0d0929a6543a64f4564b604 to your computer and use it in GitHub Desktop.
Save dillonstreator/3e9162e6e0d0929a6543a64f4564b604 to your computer and use it in GitHub Desktop.
Golang context aware `io.Copy`
type readerFunc func(p []byte) (n int, err error)

func (rf readerFunc) Read(p []byte) (n int, err error) { return rf(p) }

func Copy(ctx context.Context, dst io.Writer, src io.Reader) error {
	_, err := io.Copy(dst, readerFunc(func(p []byte) (int, error) {
		select {
		case <-ctx.Done():
			return 0, ctx.Err()
		default:
			return src.Read(p)
		}
	}))
	return err
}

OR

type contextReader struct {
	ctx context.Context
	r   io.Reader
}

func newContextReader(ctx context.Context, r io.Reader) *contextReader {
	return &contextReader{ctx, r}
}

func (r *contextReader) Read(p []byte) (int, error) {
	select {
	case <-r.ctx.Done():
		return 0, r.ctx.Err()
	default:
		return r.r.Read(p)
	}
}

func main() {
	ctx := context.Background()
	r := strings.NewReader("hello world")
	
	var buf bytes.Buffer
	io.Copy(&buf, newContextReader(ctx, r))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment