Golang标准库——io-结构

结构

LimitedReader

定义

限制从Reader中读取的字节数。

type LimitedReader struct {
    R Reader // underlying reader
    N int64  // max bytes remaining
}
方法
//Limited
func (l *LimitedReader) Read(p []byte) (n int, err error) {
        //已经读完了返回EOF
    if l.N <= 0 {
        return 0, EOF
    }
    //限制读取的长度
    if int64(len(p)) > l.N {
        p = p[0:l.N]
    }
    //直接调用Reader的Read
    n, err = l.R.Read(p)
    //更新N,保证一个LimitReader限制字节数
    l.N -= int64(n)
    return
}

SectionReader

定义

实现了对底层满足ReadAt接口的输入流某个片段的Read、ReadAt、Seek方法.

type SectionReader struct {
    r     ReaderAt      
    base  int64     //读取的起始偏移
    off   int64     //读取时的指针
    limit int64     //最终位置
}
方法

//读
func (s *SectionReader) Read(p []byte) (n int, err error) {
    //超过limit返回EOF
    if s.off >= s.limit {
        return 0, EOF
    }
    //计算最大可以读取的长度,进而修改slice
    if max := s.limit - s.off; int64(len(p)) > max {
        p = p[0:max]
    }
    //从off开始读取len(p)个字节
    n, err = s.r.ReadAt(p, s.off)
    s.off += int64(n)
    return
}

//跳转后的偏移能大于limit吗??
//Seeker
//返回跳转后与起始位置的偏移
func (s *SectionReader) Seek(offset int64, whence int) (int64, error) {
    switch whence {
    default:
        return 0, errWhence
    case SeekStart:     //SeekStart   = 0 // 相对起始位置跳转
        offset += s.base   
    case SeekCurrent:    //SeekCurrent = 1 // 相对当前位置跳转
        offset += s.off
    case SeekEnd:   //SeekEnd     = 2 // 相对最后位置跳转
        offset += s.limit
    }
    //跳转后偏移必须大于起始位置
    if offset < s.base {
        return 0, errOffset
    }
    s.off = offset
    return offset - s.base, nil
}

//off为相对base偏移量
func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) {
    //不能大于Size()
    if off < 0 || off >= s.limit-s.base {
        return 0, EOF
    }
    //设置ReadAt的初始位置,该off不能影响SectionReader.off
    off += s.base
    //计算可以读取的长度
    if max := s.limit - off; int64(len(p)) > max {
        p = p[0:max]
        n, err = s.r.ReadAt(p, off)
        //此时len(p)>max,因此需要设置文件结束的err
        if err == nil {
            err = EOF
        }
        return n, err
    }
    //可以直接读取
    return s.r.ReadAt(p, off)
}

func (s *SectionReader) Size() int64 { return s.limit - s.base }

teeReader

定义

私有结构,需要通过TeeReader函数创建一个teeReader,使读取r的数据之前均写入到w中

type teeReader struct {
    r Reader
    w Writer
}
方法
func (t *teeReader) Read(p []byte) (n int, err error) {
    //从r中读数据
    n, err = t.r.Read(p)
    if n > 0 {
        //想w写入数据
        if n, err := t.w.Write(p[:n]); err != nil {
            return n, err
        }
    }
    return
}

multiReader

定义

通过MultiReader创建,从多个Reader中连续读取

type multiReader struct {
    readers []Reader
}
方法
//实现Reader接口
//从readers中按顺序读取数据
func (mr *multiReader) Read(p []byte) (n int, err error) {
    
    for len(mr.readers) > 0 {
        // Optimization to flatten nested multiReaders (Issue 13558).
        //嵌套multiReader
        if len(mr.readers) == 1 {
            if r, ok := mr.readers[0].(*multiReader); ok {
                mr.readers = r.readers
                continue
            }
        }
        n, err = mr.readers[0].Read(p)
        //判断当前Reader是否读完
        if err == EOF {
            //释放对已读完的Reader的引用
            mr.readers[0] = eofReader{} // permit earlier GC
            //剔除第一个元素
            mr.readers = mr.readers[1:]
        }
        //如果readers还有则不能返回EOF
        if n > 0 || err != EOF {
            if err == EOF && len(mr.readers) > 0 {
                // Don't return EOF yet. More readers remain.
                err = nil
            }
            return
        }
    }
    return 0, EOF
}

multiWriter

定义

通过MultiWriter创建,每次写入数据会同时写入到这一组Writer

type multiWriter struct {
    writers []Writer
}
方法
func (t *multiWriter) Write(p []byte) (n int, err error) {
    //循环写入
    for _, w := range t.writers {
        n, err = w.Write(p)
        //某个报错则返回
        if err != nil {
            return
        }
        //必须将p都写入
        if n != len(p) {
            err = ErrShortWrite
            return
        }
    }
    return len(p), nil
}
//写字符串
func (t *multiWriter) WriteString(s string) (n int, err error) {
    var p []byte // lazily initialized if/when needed
    for _, w := range t.writers {
        //判断是否实现了stringWriter接口
        if sw, ok := w.(stringWriter); ok {
            n, err = sw.WriteString(s)
        } else {
            //将string转为slice
            if p == nil {
                p = []byte(s)
            }
            //调用Write
            n, err = w.Write(p)
        }
        if err != nil {
            return
        }
         //所有Writer必须都写完
        if n != len(s) {
            err = ErrShortWrite
            return
        }
    }
    return len(s), nil
}

pipe

定义

PipeReader和PipeWriter的底层实现

type pipe struct {
    rl    sync.Mutex // gates readers one at a time
    wl    sync.Mutex // gates writers one at a time
    l     sync.Mutex // protects remaining fields
    data  []byte     // data remaining in pending write
    rwait sync.Cond  // waiting reader
    wwait sync.Cond  // waiting writer
    rerr  error      // if reader closed, error to give writes
    werr  error      // if writer closed, error to give reads
}
方法
func (p *pipe) read(b []byte) (n int, err error) {
    // One reader at a time.
    //上Reader的锁
    p.rl.Lock()
    defer p.rl.Unlock()
    //锁其他字段
    p.l.Lock()
    defer p.l.Unlock()
    //死循环直到有数据可读了
    for {
        //reader关闭了
        if p.rerr != nil {
            return 0, ErrClosedPipe
        }
        //可以读数据了
        if p.data != nil {
            break
        }
         //writer关闭了
        if p.werr != nil {
            return 0, p.werr
        }
        //阻塞读
        p.rwait.Wait()
    }
    //读数据
    n = copy(b, p.data)
    p.data = p.data[n:]
    //pipe中数据读完了则可以notify Writer
    if len(p.data) == 0 {
        p.data = nil
        p.wwait.Signal()
    }
    return
}

func (p *pipe) write(b []byte) (n int, err error) {
    // pipe uses nil to mean not available
    if b == nil {
        b = zero[:]
    }

    // One writer at a time.
    p.wl.Lock()
    defer p.wl.Unlock()

    p.l.Lock()
    defer p.l.Unlock()
    //Writer关闭抛异常
    if p.werr != nil {
        err = ErrClosedPipe
        return
    }
    //写入数据
    p.data = b
    //notify Reader
    p.rwait.Signal()
    //阻塞,直到Reader读完
    for {
        if p.data == nil {
            break
        }
        if p.rerr != nil {
            err = p.rerr
            break
        }
        if p.werr != nil {
            err = ErrClosedPipe
            break
        }
        p.wwait.Wait()
    }
    n = len(b) - len(p.data)
    p.data = nil // in case of rerr or werr
    return
}

PipeReader/PipeWriter

定义

通过Pipe()函数创建(PipeReader, PipeWriter)

type PipeReader struct {
    p *pipe
}
type PipeWriter struct {
    p *pipe
}
方法
  • Write,调用pipe.write
  • Read,调用pipe.read

转载于:https://www.cnblogs.com/suolu/p/6731184.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值