github.com/sandwich-go/boost@v1.3.29/xio/xio.go (about)

     1  package xio
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"time"
     7  )
     8  
     9  type ioRet struct {
    10  	n   int
    11  	err error
    12  }
    13  
    14  type ctxReader struct {
    15  	r   io.Reader
    16  	ctx context.Context
    17  }
    18  
    19  // NewReader 返回context敏感的io reader
    20  func NewReader(ctx context.Context, r io.Reader) io.Reader {
    21  	return &ctxReader{ctx: ctx, r: r}
    22  }
    23  
    24  // block for debug
    25  var block = false
    26  
    27  // Read 由于Read是block操作,内部为每一次Read启动了独立协程协助读取,如果超时,则会返回(0,ctx.Error)
    28  func (r *ctxReader) Read(buf []byte) (int, error) {
    29  	bufReading := make([]byte, len(buf))
    30  
    31  	c := make(chan ioRet, 1)
    32  
    33  	go func() {
    34  		if block {
    35  			time.Sleep(10 * time.Second)
    36  		}
    37  		n, err := r.r.Read(bufReading)
    38  		c <- ioRet{n: n, err: err}
    39  		close(c)
    40  	}()
    41  
    42  	select {
    43  	case ret := <-c:
    44  		copy(buf, bufReading)
    45  		return ret.n, ret.err
    46  	case <-r.ctx.Done():
    47  		return 0, r.ctx.Err()
    48  	}
    49  }