65 lines
2.1 KiB
Markdown
65 lines
2.1 KiB
Markdown
# CancelReader
|
|
|
|
[](https://github.com/muesli/cancelreader/releases)
|
|
[](https://pkg.go.dev/github.com/muesli/cancelreader)
|
|
[](/LICENSE)
|
|
[](https://github.com/muesli/cancelreader/actions)
|
|
[](https://goreportcard.com/report/muesli/cancelreader)
|
|
|
|
A cancelable reader for Go
|
|
|
|
This package is based on the fantastic work of [Erik Geiser](https://github.com/erikgeiser)
|
|
in Charm's [Bubble Tea](https://github.com/charmbracelet/bubbletea) framework.
|
|
|
|
## Usage
|
|
|
|
`NewReader` returns a reader with a `Cancel` function. If the input reader is a
|
|
`File`, the cancel function can be used to interrupt a blocking `Read` call.
|
|
In this case, the cancel function returns true if the call was canceled
|
|
successfully. If the input reader is not a `File`, the cancel function does
|
|
nothing and always returns false.
|
|
|
|
```go
|
|
r, err := cancelreader.NewReader(file)
|
|
if err != nil {
|
|
// handle error
|
|
...
|
|
}
|
|
|
|
// cancel after five seconds
|
|
go func() {
|
|
time.Sleep(5 * time.Second)
|
|
r.Cancel()
|
|
}()
|
|
|
|
// keep reading
|
|
for {
|
|
var buf [1024]byte
|
|
_, err := r.Read(buf[:])
|
|
|
|
if errors.Is(err, cancelreader.ErrCanceled) {
|
|
fmt.Println("canceled!")
|
|
break
|
|
}
|
|
if err != nil {
|
|
// handle other errors
|
|
...
|
|
}
|
|
|
|
// handle data
|
|
...
|
|
}
|
|
```
|
|
|
|
## Implementations
|
|
|
|
- The Linux implementation is based on the epoll mechanism
|
|
- The BSD and macOS implementation is based on the kqueue mechanism
|
|
- The generic Unix implementation is based on the posix select syscall
|
|
|
|
## Caution
|
|
|
|
The Windows implementation is based on WaitForMultipleObject with overlapping
|
|
reads from CONIN$. At this point it only supports canceling reads from
|
|
`os.Stdin`.
|