package networking import ( "io" ) type AsyncReader struct { BufSize int stream io.ReadCloser dataChan chan []byte stopFlag bool } // NewListen starts listening for a single connection on the given address. // This method blocks until this is done. func NewAsyncReader(reader io.ReadCloser) *AsyncReader { return &AsyncReader{ BufSize: defaultBufSize, stream: reader, stopFlag: false, } } // RecvChan returns a read-only channel of byte slices and starts // receiving and pushing data into it asynchronously. // The channel is closed when the sender closes the connection. // Use this to read bytes from the network connection. // The data read is owned by the reader, it is thread-safe to modify. func (ar *AsyncReader) RecvChan() <-chan []byte { ar.dataChan = make(chan []byte) go ar.recvLoop() return ar.dataChan } func (ar *AsyncReader) recvLoop() { buf := make([]byte, ar.BufSize) for !ar.stopFlag { n, err := ar.stream.Read(buf) if err != nil { ar.stopFlag = true } if n > 0 { // the underlying memory of the buffer // must be copied for thread safety sendBuf := make([]byte, n) copy(sendBuf, buf) ar.dataChan <- sendBuf } } close(ar.dataChan) } func (ar *AsyncReader) Close() { ar.stopFlag = true ar.stream.Close() }